-
Notifications
You must be signed in to change notification settings - Fork 4
CLI Machines Remote Exec
Runs one command on one machine and gets out of the way. Both output streams
stay separate, the remote exit code becomes yours, and the only byte ed adds
is the newline it puts back on a last line that had none.
ed machines exec [--tty] <machine> [--] <command...>
ed machines run [--tty] <machine> [--] <command...>
| Name | Type / values | Default | What it does |
|---|---|---|---|
<machine> |
machine name, ssh config alias, id, or an unambiguous prefix of a name or alias | none, required | Which machine to run on. Matched case-insensitively: exact name first, then ssh alias, then UUID, then a unique prefix. |
<command...> |
one or more words | none, required | The command to run. A single leading -- is dropped before anything is sent. |
| Name | Type / values | Default | What it does |
|---|---|---|---|
--tty, -t
|
flag | off | Allocate a terminal for the command with ssh -tt. Needed by anything interactive; wrong for scripting. |
--help, -h
|
flag | off | Print the help for this command on stdout and exit 0. |
--version |
flag | off | Print the CLI version, 1.0.0, and exit 0. Generated by the parser and accepted here as well as at the root. |
Every one of these has to come before the machine name. The command array is
captured for passthrough, so the parser stops reading options at the first
positional word: in ed machines exec tuf --tty top the --tty is part of the
command and is sent to the machine, where it is not a program:
$ ed machines exec tuf --tty top
bash: line 1: --tty: command not found
$ echo $?
127
There is no --json. ed machines exec is one of the handful of commands that
do not offer it, because the bytes on stdout belong to the remote process and
wrapping them would break every pipe. --json before the machine name is an
unknown option and exits 2.
ed machines exec tuf uptime
ed machines exec tuf -- ls -la /etc
ed machines exec --tty tuf top
ed machines run tuf systemctl status nginx
Nothing local is mutated except the remembered working directory, which only
cd writes, and what opening the connection leaves behind: the ControlMaster
socket and the host key pinned beside it. The machine is resolved from Edith's
own machine list, so a host is never retyped, and the connection is opened
before the command runs: if a ControlMaster socket for that machine is already
alive, from the app or from an earlier ed, the command is one round trip on
it, and if there is not, ed opens one that outlives the process by
ControlPersist=10m.
How the words become a command line depends on how many there are. One word is sent verbatim, which is the one-shot escape hatch for anything the remote shell has to interpret. Several words are quoted individually and joined, so an argument with spaces survives and a shell metacharacter does not:
$ ed tuf echo 'a;pwd'
a;pwd
$ ed tuf 'ls /etc | head -3'
adduser.conf
alsa
alternatives
A word is left unquoted only when every character in it is a letter, a digit or
one of . _ - + / = : @ % ,. Everything else is wrapped in single quotes, which
covers spaces, ~, *, $, |, >, ;, & and quotes themselves. So
ed tuf ls '*.log' does not glob on the machine, and ed tuf ls '~/Desktop'
does not expand the tilde; quote the whole line instead when you want either.
--tty builds its command line differently: the words are joined with single
spaces and nothing is quoted, because the point of a terminal session is to let
the remote shell parse the line. The same input therefore behaves differently
under the two paths:
$ ed machines exec --tty tuf echo 'a;pwd'
a
/home/pulkit
Shared connection to 192.168.1.12 closed.
That trailing line is ssh's own, on stderr, and appears on every --tty run.
Stdin is not forwarded on the plain path. The remote process is given
/dev/null, so printf 'x\n' | ed tuf cat prints nothing and
ed tuf wc -l < file counts zero. With --tty your terminal is handed
straight to ssh and typing works, but a redirected file or a pipe still will
not end the command: the remote side sees a terminal rather than a closed pipe,
so a cat with nothing more to read waits instead of exiting. Feed data to a
machine with ed machines files put or by quoting a line that reads the file on
the far side.
Output is read line by line off two pipes and re-emitted, stdout to stdout and
stderr to stderr, so a partial last line with no newline is still printed and
the exact interleaving of the two streams is not guaranteed to match what the
machine produced. There is no timeout: ed tuf tail -f /var/log/syslog streams
until you interrupt it.
The exit code is the remote command's, verbatim and unclamped, which is the one
documented exception to ed's 0 to 4 contract:
$ ed tuf exit 42
$ echo $?
42
Naming no command at all fails before anything is dialled, and the error names the machine you gave:
$ ed machines exec tuf
error: name a command to run, for example `ed tuf uptime`
The command runs in whatever directory ed <machine> cd last set for this
terminal, on both the plain and the --tty path. That is a cd prefix on the
line ssh is given, cd '<directory>' 2>/dev/null || cd;, so a directory that
has since been deleted quietly falls back to the home directory rather than
failing every command after it.
- Running commands on a machine, the rest of this group
- All
edcommands
Auto-generated from docs/, edit the docs in the repo, not the wiki.
CLI reference
Companion
- Deploy
- Concepts
- Concepts Memory
- Concepts Ingestion
- Concepts Search
- Concepts Chat
- Concepts Learning
- Concepts Brain
- Concepts Friend
- Hosts
- Stack
- Status
- Doctor
- Search
- Index
- Ingest
- Episodes
- Sync
- Observations
- Reflect
- Beliefs
- Ask
- Extract
- Claims
- Corroborate
- Runs
- Chat
- Conversations
- Forget
- Export
- Import
- Erase
- Wipe
- Episode
- Nightly
- Reason
- Personas
- Council
- Lenses
- Core
- Why
- Hypotheses
- Predictions
- Commitments
- Discrepancies
- Calibration
- Inquire
- Entities
- Eval
- Standup
- Machines
- Baselines
- Connectors
- Facts
- Correct
- Weekly
- Db
Guides