Sample Header Ad - 728x90

runuser: execute commands without use of quotation marks?

-2 votes
2 answers
619 views
## Overview I'm attempting to execute commands as a different user **without using quotation marks** as well as making sure the executed command **isn't inheriting environment** from the parent shell. [runuser](https://man.archlinux.org/man/runuser.1.en) looks like the perfect candidate for this job as it's going to be executed by a privileged user *(in a unattended script)*, there's no setuid bit, has login/PAM session support and it's a part of widely used util-linux package. ## Problem Edit: to clarify further: > The culprit here is that I'd like to switch between multiple users _within_ the same script and execute the commands _as they are written_ from the perspective of the user executing them. Currently variables like $USER or even ~/ gets expanded to the values from parent shell which breaks the entire setup. For a long time I've been using Bash's -c but this requires quotation marks which makes commands with e.g. regex difficult to read. Original question: > The goal is to display directory listening of user's home (meaning ~/ should translate to /home/build) as the build user _(where's a "polluted" shell would return /root)_. Quotation marks should not be used _(to avoid having to escape those with more advanced commands)_. The following approach almost works but it unfortunately inherits environment from parent's session:
$ whoami
root

$ runuser --user build -- ls -a ~/
ls: cannot open directory '/root/': Permission denied
Another alternative which I've tried is to create a login session but due to the nature of Bash, the arguments aren't parsed as [command_string](https://man.archlinux.org/man/bash.1.en#c) but instead as a script:
$ runuser --login build -- ls -a ~/
/usr/bin/ls: /usr/bin/ls: cannot execute binary file
Logically this is usually solved by supplying the -c argument to Bash but this bring us back to square one, it requires quotation marks:
$ runuser --login build -- -c 'set -x; ls -a ~/'
+ ls -a /home/build/
Invoking a _separate_ script fulfills all the requirements but I found this approach to be cumbersome to work with:
# run.sh
whoami
ls -a ~/
$ chown build run.sh
$ chmod +x run.sh
$ runuser build ./test.sh 
+ whoami
build
+ ls -a /home/build/
## Question Are there any other approaches which allows you to avoid quotation marks when executing commands as a different user in a clean environment? --- #### Update 1 Heredoc is the closest solution which fits all criteria but I'm happy to hear if there's more!
# run.sh
runuser --user build -- bash << EOF
set -x
ls -d ~/
whoami
EOF

# Result
+ ls -d /home/build/
/home/build/
+ whoami
build
#### Update 2 Exporting functions to subshells is also viable and preserves syntax highligh
function CMD {
  set -x
  echo $USER
  ls -d ~/
}
runuser --login build -- -c "$(declare -f CMD); CMD"
Asked by GrabbenD (170 rep)
Jul 6, 2024, 04:14 PM
Last activity: Sep 15, 2024, 08:07 AM