This would have probably been answered by Keep running a script via ssh, if I didn't have to run a command as superuser. Let me try with an example: say on my server, I have this script as ~/testsleep.sh, which is also chmod +x:

#!/usr/bin/env bash

logger Pre sleep: "$USER" / "$USERNAME" / "$1"

sleep 5

logger Post sleep: "$USER" / "$USERNAME" / "$1"

I want to have logger log to /var/log/syslog, since via ssh I'm likely to lose stdout/stderr.

Say I run this on my local PC, logged in via ssh to the remote server:

server$ readlink -f ~/testsleep.sh 

server$ $ ls -la testsleep.sh 
-rwxr-xr-x 1 user user 126 2015-02-05 13:35 testsleep.sh

server$ sudo /home/user/testsleep.sh some_argument
sudo: unable to execute /home/user/testsleep.sh: No such file or directory

The first problem is that I cannot run the script directly with sudo, even if it is executable; I think this has to do with "your current shell is running under your regular user ID ... and there is no way to grant it root access" Execute a shell script in current shell with sudo permission - Stack Overflow

Ok, fine, I'll run sudo bash - this looks more like it:

server$ sudo bash /home/user/testsleep.sh some_argument

server$ tail -2 /var/log/syslog
Feb  5 13:40:48 user user: Pre sleep: root / root / some_argument
Feb  5 13:40:53 user user: Post sleep: root / root / some_argument

So, apparently the script does log in syslog, and sees root as $USER; as intended. So far, so good.

Now, I'd like to run this script as a process on the server, right before I exit my ssh terminal session. I guess I'd do this:

server$ sudo bash /home/user/testsleep.sh from_end & exit
[1] 6293
Connection to closed.

If I log back in into the server, and check syslog again, I can see that there is no log from this last, "exiting" invocation:

# this `grep` will print the filename, if file doesn't contain the match:

server$ grep --files-without-match 'from_end' /var/log/syslog
server$ tail -2 /var/log/syslog
Feb  5 13:40:48 mypc user: Pre sleep: root / root / some_argument
Feb  5 13:40:53 mypc user: Post sleep: root / root / some_argument

So, my question is - how can I run this script as a process, under sudo on the server - but invoked from an ssh shell, and right before exiting it; so that it runs (in this case, confirmed by writing to the syslog)?


You need to disown the job so it doesn't get killed when the connection is "hung up":

sudo bash /home/user/testsleep.sh from_end & sleep 1; disown -h; exit

The sleep 1 is in there to reduce the race between the background job starting and the shell exiting. If you can avoid having to do everything in a single line you'll get better results separating the two sets of commands:

sudo bash /home/user/testsleep.sh from_end &
disown -h; exit
  • Many thanks for that, @StephenKitt, that seems to work great! Just a note: if I forget to do say sudo ls before I execute the command, so that my password is asked for and temporarily remembered, then I might get [1]+ Stopped sudo bash /home/user/testsleep.sh from_end ; logout ; There are stopped jobs., so I had to do fg until I saw and answered the password prompt. Btw, in syslog I get mypc user: Pre sleep: root...but mypc logger: Post sleep: root... - any idea why "pre sleep" has user and "post sleep" has logger as username? – sdaau Feb 5 '15 at 14:00
  • 1
    The sudo prompt is normal if that execution needs a password. At least you get a chance to fix the problem ;-). As to logger appearing in the log instead of user, I can hazard a guess but I'd rather check. – Stephen Kitt Feb 5 '15 at 14:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.