Bash, Execute Command But Continue with Interactive Session

Bash, execute command but continue with interactive session

My advice would be using a custom bashrc file with --rcfile that sources your .bashrc, ex :

alias admin=pagsh -c "bash --rcfile myrc"

myrc :

source ~/.bashrc
kinit xtoth1@ADMIN.META

How to invoke bash, run commands inside the new shell, and then give control back to user?

bash --rcfile <(echo '. ~/.bashrc; some_command')

dispenses the creation of temporary files. Question on other sites:


run bash command in new shell and stay in new shell after this command executes

You can achieve something similar by abusing the --rcfile option:

bash --rcfile <(echo "export PS1='> ' && ls")

From bash manpage:

--rcfile file

Execute commands from file instead of the system wide initialization file /etc/bash.bashrc and the standard personal initialization file ~/.bashrc if the shell is interactive

Run a command in a shell and keep running the command when you close the session

nohup, disown, and screen are all good but screen is the best because unlike the other two, screen allows you to disconnect from the remote server, keep everything running, and then reconnect later to see what is happening. With nohup and disown you can't resume interacting.

Run ssh and immediately execute command

ssh -t 'command; bash -l'

will execute the command and then start up a login shell when it completes. For example:

ssh -t user@domain.example 'cd /some/path; bash -l'

How to wait in bash for several subprocesses to finish, and return exit code !=0 when any subprocess ends with code !=0?

wait also (optionally) takes the PID of the process to wait for, and with $! you get the PID of the last command launched in the background.
Modify the loop to store the PID of each spawned sub-process into an array, and then loop again waiting on each PID.

# run processes and store pids in array
for i in $n_procs; do
./procs[${i}] &

# wait for all pids
for pid in ${pids[*]}; do
wait $pid

What is the cleanest way to ssh and run multiple commands in Bash?

How about a Bash Here Document:

ssh otherhost << EOF
ls some_folder;
./ 'some params'
./some_other_action 'other params'

To avoid the problems mentioned by @Globalz in the comments, you may be able to (depending what you're doing on the remote site) get away with replacing the first line with

ssh otherhost /bin/bash << EOF

Note that you can do variable substitution in the Here document, but you may have to deal with quoting issues. For instance, if you quote the "limit string" (ie. EOF in the above), then you can't do variable substitutions. But without quoting the limit string, variables are substituted. For example, if you have defined $NAME above in your shell script, you could do

ssh otherhost /bin/bash << EOF
touch "/tmp/${NAME}"

and it would create a file on the destination otherhost with the name of whatever you'd assigned to $NAME. Other rules about shell script quoting also apply, but are too complicated to go into here.

SSH into a box, immediately background the process, then continue as the original user in a bash script

My goal is to run systemctl --user commands as root via script. If your familiar with systemctl --user domain, there is no way to manage systemctl --user units, without the user being logged in via traditional methods (ssh, direct terminal, or gui). I cannot "su - user1" as root either. So I want to force an ssh session as root to the vdns11 user via runuser commands. Once the user is authenticated and shows up via who I can run systemctl --user commands. How can I keep the ssh session active in my code?

With this additional info, the question essentially boils down to 'How can I start and background an interactive ssh session?'.

You could use script for that. It can be used to trick applications into thinking they are being run interactively:

echo "[+] Starting SSH session in background"
runuser -l user1 -c "script -c 'ssh localhost'" &>/dev/null &
echo "[+] Killing active SSH session"
kill ${pid}

Original answer before OP provided additional details (for future reference):

Let's dissect what is going on here.

I assume you start your script as root:

echo "[+] Becoming user1"
runuser -l user1 -c 'ssh -q localhost 2>/dev/null' &

So root runs runuser -l user1 -c '...', which itself runs ssh -q localhost 2>/dev/null as user1. All this takes place in the background due to &.

ssh will print Pseudo-terminal will not be allocated because stdin is not a terminal. (hidden due to 2>/dev/null) and immediately exit. That's why you don't see anything when running who or when running ps.

Your echo says [+] Becoming user1, which is quite different from what's happening.

sleep 1

The script sleeps for a second. Nothing wrong with that.

echo "[+] Running systemctl --user commands as root."
#runuser -l user 1 -c 'systemctl --user list-units'
# ^ typo!
runuser -l user1 -c 'systemctl --user list-units'

Ignoring the typo, root again runs runuser, which itself runs systemctl --user list-units as user1 this time.

Your echo says [+] Running systemctl --user commands as root., but actually you are running systemctl --user list-units as user1 as explained above.

echo "[+] Killing active ssh sessions."
kill $(ps aux | grep ssh | grep "^user1.*" | grep localhost | awk '{print$2}') 2>/dev/null

This would kill the ssh process that had been started at the beginning of the script, but it already exited, so this does nothing. As a side note, this could be accomplished a lot easier:

echo "[+] Becoming user1"
runuser -l user1 -c 'ssh -q localhost 2>/dev/null' &
echo "[+] Killing active ssh sessions."
kill $(pgrep -P $pid)

So this should give you a better understanding about what the script actually does, but between the goals you described and the conflicting echos within the script it's really hard to figure out where this is supposed to be going.

Related Topics

Leave a reply