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
Last activity: Sep 15, 2024, 08:07 AM