| name | openwrt-ssh-pct-remote |
| description | OpenWrt pct_remote shell syntax and SSH connection patterns. Use when running commands in OpenWrt containers via Proxmox, managing LXC containers, or debugging SSH connectivity issues. |
OpenWrt pct_remote Shell Syntax Rules
Shell Execution Through pct_remote
- The
community.proxmox.proxmox_pct_remote connection plugin builds /usr/sbin/pct exec <vmid> -- <cmd> and sends it as a single string via SSH to the Proxmox host. The HOST's bash interprets the entire string before pct exec runs.
Critical Shell Syntax Issues
-
Semicolons split at host level. cmd1; cmd2 becomes two separate commands on the Proxmox host — only cmd1 runs inside the container.
-
Pipes split at host level. cmd1 | cmd2 — cmd1 runs inside the container, cmd2 runs on the HOST (filtering stdout from the container). This happens to work for text processing but is fragile.
-
export is NOT a binary. lxc-attach tries to exec the first word of the command as a binary. export is a shell builtin — it fails with lxc-attach: Failed to exec "export".
-
PATH is not set inside the container. lxc-attach's execvp uses the default path (/bin:/usr/bin), which misses /sbin and /usr/sbin where OpenWrt puts uci, wifi, iw.
Solution: sh -c Wrapper Pattern
- ALWAYS wrap all commands in
/bin/sh -c '...'. The single quotes protect the payload from host bash. Inside the container, busybox ash provides its default PATH=/sbin:/usr/sbin:/bin:/usr/bin.
- ansible.builtin.raw: >-
export PATH="/usr/sbin:/usr/bin:/sbin:/bin:$PATH";
opkg update
- ansible.builtin.raw: >-
for mod in iwlwifi ath9k; do modprobe "$mod" 2>/dev/null; done
- ansible.builtin.raw: >-
/bin/sh -c 'opkg update'
- ansible.builtin.raw: >-
/bin/sh -c
'opkg list-installed 2>/dev/null | grep -c wpad-mesh || true'
- ansible.builtin.raw: >-
/bin/sh -c
'uci set wireless.mesh0=wifi-iface &&
uci set wireless.mesh0.device="radio0" &&
uci commit wireless'
Quoting Rules for sh -c Through pct_remote
-
Outer single quotes protect the entire payload from host bash.
-
Inside, use double quotes for values: uci set foo.bar="value"
-
NEVER nest single quotes — use double quotes or drop quotes for simple alphanumeric values.
-
&& and || inside single quotes are interpreted by container ash.
-
[ ... ] && echo x || echo y WITHOUT sh -c is OK — [ is exec'd by lxc-attach, &&/|| chain at host level (works for simple checks).
pct exec PATH Limitation
-
pct exec (and lxc-attach) uses a restricted PATH: /sbin:/bin:/usr/sbin:/usr/bin. Binaries in /usr/local/bin/ (e.g., pihole) are NOT found.
-
ALWAYS use full paths for binaries in /usr/local/bin/ or /opt/ when running via pct exec, pct_remote, or ansible.builtin.command on containers.
-
Previous bug: pihole -a -p via pct_remote failed with [Errno 2] No such file or directory: b'pihole'. The binary was at /usr/local/bin/pihole but PATH didn't include it.