lxc-attach(1)

πŸ’… lxc-attach β€” the "get me INSIDE that container" command

okay bestie, so this is the manual page for lxc-attach(1) β€” a little tool that lets you start a process inside a container that's already running. no reboots, no drama, just vibes. let's go ✨


🌸 NAME 🌸

lxc-attach β€” start a process inside a running container.


πŸŽ€ SYNOPSIS πŸŽ€

lxc-attach {-n, --name name} [-f, --rcfile config_file] [-a, --arch
           arch] [-e, --elevated-privileges privileges] [-s,
           --namespaces namespaces] [-R, --remount-sys-proc] [--keep-
           env] [--clear-env] [-v, --set-var variable] [--keep-var
           variable] [-u, --uid uid] [-g, --gid gid] [-- command]

✨ DESCRIPTION ✨

So lxc-attach runs the command you give it inside the container you named with name. the container has to already be running β€” we are NOT starting it for you, that's a different command, iykyk.

If you don't specify a command at all? It goes and looks up the current default shell of the user running lxc-attach, inside the container, and executes that. and ngl, that can absolutely flop: it fails if no such user exists inside the container, or if the container doesn't have a working nsswitch mechanism. πŸ’€

okay history lesson, because it matters. Old versions of lxc-attach just attached to the namespaces you told it to and ran a shell or your command without allocating a pseudo terminal first. and that made them vulnerable to input faking via a TIOCSTI ioctl call, once you'd switched between userspace execution contexts with different privilege levels. NOT cute. 😭

Newer versions of lxc-attach try to allocate a pseudo terminal file descriptor pair on the host, and attach any standard file descriptors that refer to a terminal to the container side of that pseudo terminal, all before executing the shell or command.

but heads up β€” if none of the standard file descriptors refer to a terminal, lxc-attach will not try to allocate a pseudo terminal at all. it'll just attach to the container's namespaces and run the shell or the specified command, plain and simple. ✨


πŸ’– OPTIONS πŸ’–

  • -f, --rcfile config_file β€” pick the config file that sets up the virtualization and isolation functionalities for the container. and bestie, this config file, if it's there, will be used even if there's already a config file present in the container you made earlier (via lxc-create). yeah. it wins.
  • -a, --arch arch β€” tell the kernel which architecture it should appear to be running as, from the point of view of the command being executed. this option accepts the same settings as the lxc.arch option in container configuration files β€” go peek at lxc.conf(5). by default, the current architecture of the running container gets used.
  • -e, --elevated-privileges privileges β€” do NOT drop privileges when running the command inside the container. if you use this, the new process will not be added to the container's cgroup(s), and it will not drop its capabilities before executing. spicy.

if you don't want to elevate all of them, you can name the privileges you do want as a pipe-separated list, e.g. CGROUP|LSM. the allowed values are CGROUP, CAP and LSM, standing for cgroup, capabilities and restriction privileges respectively. (and bestie, that pipe symbol needs escaping, e.g. CGROUP\|LSM, or quoting, e.g. "CGROUP|LSM".)

Warning: this may leak privileges into the container if the command starts subprocesses that stay active after the main process that was attached is terminated. (re-)starting daemons inside the container is genuinely problematic, especially if the daemon spawns a lot of subprocesses like cron or sshd. use with great care, fr fr. πŸ™ˆ
  • -s, --namespaces namespaces β€” say which namespaces to attach to, as a pipe-separated list, e.g. NETWORK|IPC. allowed values are MOUNT, PID, UTSNAME, IPC, USER and NETWORK. this is how you change the context of the process to, say, the network namespace of the container while keeping all the other namespaces as those of the host. (the pipe symbol needs escaping, e.g. MOUNT\|PID, or quoting, e.g. "MOUNT|PID".)
Important: this option implies -e.
  • -R, --remount-sys-proc β€” when you're using -s and the mount namespace is not included, this flag makes lxc-attach remount /proc and /sys so they reflect the current other namespace contexts. more deets in the Notes section below πŸ‘‡. also, this option gets ignored entirely if you try to attach to the mount namespace anyway.
  • --keep-env β€” keep the current environment for the attached programs. this is the current default behaviour (as of version 0.9), but it is likely to change in the future, since this may leak undesirable information into the container. so if you rely on the environment being available for the attached program, pls use this option to be future-proof. on top of the current environment variables, container=lxc will be set.
  • --clear-env β€” clear the environment before attaching, so no undesired environment variables leak into the container. the variable container=lxc will be the only environment the attached program starts with.
  • -v, --set-var variable β€” set an extra environment variable that the attached program sees inside the container. you write it in the form "VAR=VALUE", and you can specify it multiple times.
  • --keep-var variable β€” keep one specific environment variable. it can only be specified together with --clear-env, and you can specify it multiple times.
  • -u, --uid uid β€” executes the command with user ID (use a numerical value) uid inside the container.
  • --g, --gid gid β€” executes the command with group ID (use a numerical value) gid inside the container.

πŸ¦‹ COMMON OPTIONS πŸ¦‹

these ones are common to most of the lxc commands, so like, shared bestie energy. 🫢

  • -?, -h, --help β€” print a longer usage message than normal.
  • --usage β€” give the usage message.
  • -q, --quiet β€” mute on.
  • -P, --lxcpath=PATH β€” use an alternate container path. the default is /var/lib/lxc.
  • -o, --logfile=FILE β€” output to an alternate log FILE. the default is no log.
  • -l, --logpriority=LEVEL β€” set log priority to LEVEL. the default log priority is ERROR. possible values are: FATAL, ALERT, CRIT, WARN, ERROR, NOTICE, INFO, DEBUG, TRACE.

note that this option sets the priority of the events log in the alternate log file. it does not have an effect on the ERROR events log on stderr.

  • -n, --name=NAME β€” use container identifier NAME. the container identifier format is an alphanumeric string.
  • --rcfile=FILE β€” specify the configuration file to configure the virtualization and isolation functionalities for the container.

this configuration file, if present, will be used even if there's already a configuration file present in the previously created container (via lxc-create).

  • --version β€” show the version number.

πŸ”₯ EXAMPLES πŸ”₯

wanna spawn a whole new shell running inside an existing container? iconic, do this:

lxc-attach -n container

wanna restart the cron service of a running Debian container? say less:

lxc-attach -n container -- /etc/init.d/cron restart

now, wanna deactivate the network link eth1 of a running container that does not have the NET_ADMIN capability? you've got two routes, bestie. option one: use the -e option to get increased capabilities, assuming the ip tool is installed:

lxc-attach -n container -e -- /sbin/ip link delete eth1

or, alternatively, use -s so you're using the tools installed on the host outside the container:

lxc-attach -n container -s NETWORK -- /sbin/ip link delete eth1

🌈 COMPATIBILITY 🌈

attaching completely (which means including the pid and mount namespaces) to a container requires a kernel of version 3.8 or higher, or a patched kernel β€” please see the lxc website for details. lxc-attach will fail in that case if used with an unpatched kernel of version 3.7 and prior. πŸ’€

nevertheless! it will succeed on an unpatched kernel of version 3.0 or higher if the -s option is used to restrict the namespaces that the process is to be attached to, down to one or more of NETWORK, IPC and UTSNAME.

attaching to user namespaces is supported by kernel 3.8 or higher with user namespace enabled.


⭐ NOTES ⭐

so the Linux /proc and /sys filesystems contain information about some quantities that are affected by namespaces β€” like the directories named after process ids in /proc, or the network interface information in /sys/class/net. and here's the tea: it's the namespace of the process mounting the pseudo-filesystems that determines what information is shown. not the namespace of the process accessing /proc or /sys. wild, right.

so if you use the -s option to only attach to the pid namespace of a container, but not its mount namespace (which would contain the container's /proc and not the host's), then the contents of /proc will reflect the host's, not the container's. and analogously, the exact same issue shows up when you read the contents of /sys/class/net and attach to just the network namespace. 😭

to work around this problem, the -R flag gives you the option to remount /proc and /sys so they reflect the network/pid namespace context of the attached process. and in order not to interfere with the host's actual filesystem, the mount namespace will be unshared (like lxc-unshare does) before this is done β€” which essentially gives the process a brand new mount namespace, identical to the host's mount namespace except for the /proc and /sys filesystems. chef's kiss. πŸ‘‘

also, previous versions of lxc-attach suffered a bug whereby a user could attach to a container's namespace without being placed in a writeable cgroup for some critical subsystems. newer versions of lxc-attach will check whether a user is in a writeable cgroup for those critical subsystems. so lxc-attach might thus fail unexpectedly for some users (e.g. on systems where an unprivileged user is not placed in a writeable cgroup in critical subsystems on login). however! this behavior is correct and more secure. so we stan it. πŸ’…


🧚 SECURITY 🧚

the -e and -s options should be used with care, because it may break the isolation of the containers if used improperly. that's it, that's the warning. be careful bestie. 🚨


πŸ’œ SEE ALSO πŸ’œ

lxc(7), lxc-create(1), lxc-copy(1), lxc-destroy(1), lxc-start(1), lxc-stop(1), lxc-execute(1), lxc-console(1), lxc-monitor(1), lxc-wait(1), lxc-cgroup(1), lxc-ls(1), lxc-info(1), lxc-freeze(1), lxc-unfreeze(1), lxc-attach(1), lxc.conf(5)


and that's the whole page, bestie πŸŽ€ this was lxc-attach(1) from the lxc docs, dated 2026-09-15. go forth and attach responsibly, mwah πŸ’‹βœ¨

πŸ“¦ where this page comes from