8

I have a systemd container running, and I can login into it with machinectl login <container>. How can I execute a command inside the container directly, i.e. without first logging in, executing the command, and then logging out?

Another way to put it is that I'm looking for the systemd equivalent of:

$ docker exec <container> <command> 

or

$ ssh <host> <command>
slm
  • 363,520
  • 117
  • 767
  • 871
Ilari Scheinin
  • 243
  • 2
  • 7
  • 1
    Run a `sshd` or something that keeps listening inside then. Or let `expect` get the password-input job done. – Mingye Wang Oct 25 '15 at 09:13
  • Both suggestions sound like workarounds for something that should be possible directly. But maybe `systemd` just isn't there yet. A small `expect` script gets the job done nicely. Thanks, @Arthur2e5. – Ilari Scheinin Oct 26 '15 at 11:30
  • To be honest, I often treat a container as a real machine and I run `sshd` on say, port 61022 inside. – Mingye Wang Oct 26 '15 at 12:36
  • similar question (for others searching): https://unix.stackexchange.com/q/302239/4808 –  Sep 21 '17 at 08:15

2 Answers2

8

Try systemd-run:

# systemd-nspawn -D <machine-root> -b 3 --link-journal host

# systemd-run --machine <machine-name> env
Running as unit run-1356.service.

# journalctl --machine <machine-name> -u run-1356 -b -q
Oct 30 07:45:09 jessie-64 systemd[1]: Started /usr/bin/env.
Oct 30 07:45:09 jessie-64 env[37]: PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

Excerpt from the manpage:

Use shell (see below) or systemd-run(1) with the --machine= switch to directly invoke a single command, either interactively or in the background.

(The command shell available since v225)

Evgeny Vereshchagin
  • 5,286
  • 4
  • 35
  • 43
  • Thanks. I have v215, so don't have `shell`, but `systemd-run` works. This I find weird though: In `systemd-run [OPTIONS...] COMMAND [ARGS...]`, if for `COMMAND` I use the path inside the container, I (immediately) get an error saying `Failed to find executable /container/path.sh: No such file or directory`. And if I give the full host path, I (through `journalctl`) get an error saying `Failed at step EXEC spawning /var/lib/machines//container/path.sh: No such file or directory`. Since mine is a shell script, I can use `/bin/sh /container/path.sh`, but there must be a "correct" way. – Ilari Scheinin Nov 02 '15 at 08:25
  • 1
    @IlariScheinin, that was [fixed](https://github.com/systemd/systemd/commit/85eca92e2061043d733991b386d8dc10fad0fc30): "It's not reasonably possible to look for binaries on remote systems, we hence should not pretend we could." – Evgeny Vereshchagin Nov 02 '15 at 08:59
3

For systems without machinectl shell (e.g. systemd v219 on CentOS 7 Atomic) or during situations where machinectl login fails for any reason, you can get a shell or run commands directly using nsenter:

Example:

$ nsenter \
     --target=$(machinectl show --property Leader ipsec-libreswan | sed "s/^Leader=//") \
     --mount --uts --ipc --net --pid
slm
  • 363,520
  • 117
  • 767
  • 871
jwmullally
  • 131
  • 2