I've created a script in /etc/init.d/ which has to run several other scripts from other (non-root privileged) users from their home directories, as if they started them.
I launch these scripts with: sudo -b -u <username> <script_of_a_particular_user>
And it works. But for every user script that continues running(for example some watchdog) I see a corresponding parent sudo process, still alive and running as root. This creates a mess in the active processes list.
So my question is: How can I launch(fork) another script from existing bash script as another user and leave it as an orphaned(stand alone) process?
More detailed explanation:
I'm basically trying to provide to other users on the machine a mean to run stuff upon system start or system shutdown by running executable files found in respective subdirectories found in their home directory, named .startUp and .shutDown.
Since I did not find any other means to do that I wrote my bash script that does exactly that and I've configured it as a service script (by following the skeleton example) in /etc/init.d/ so when it is run with start argument it launches everything from .startUp directories and when it is run with stop argument it launches everything from .shutDown directories of all users as them.
Alternatively I'm also interested if I could have used some existing solution to solve this problem.
UPDATE
I've looked around a bit and I found this question:
https://unix.stackexchange.com/questions/22478/detach-a-daemon-using-sudo
Accepted answer there, to use: sudo -u user sh -c "daemon & disown %1"
, works for me to. But I also tried without disown %1 and it is the same. So this is what works for me as I expected:
sudo -u <username> bash -c "<script_of_a_particular_user> &"
My additional question now is, why is it working without disown? should I still leave the disown call, regardless, for some potential special case?
UPDATE 2
Apparently this works too:
su <username> -c "<script_of_a_particular_user> &"
Is there any difference between this call and the sudo call? I know this is potentially an entire different question. But since I'm finding the answers here myself maybe for the sake of this topic someone could clarify this here.
UPDATE 3
Both of these methods with either su or sudo now produce a new startpar process (single process that runs as root) after I boot the machine. Visible in process list as:
startpar -f -- <name_of_my_init.d_script>
Why is this process spawned? Obviously I'm doing something wrong since no other init.d script has this process running.
UPDATE 4
The issue with startpar is resolved. I've started another question for that:
startpar process left hanging when starting processes from rc.local or init.d
And another question to further discuss launching mechanisms for non privileged users:
Providing normal users(non-root) with initialization and shutdown auto-run capabilities
The correct answer for this was that for proper "daemonization", standard input, standard output and standard error need to be redirected to /dev/null (or some real file):
su - substitute user identity to someuser
-c - su argument to run specified command
nohup - Run a command immune to hangups. To prevent cases where parent process will terminate the child process. Added here just in case. But actually has no effect in my particular case. Whether it is needed depends on the environment(check shopt)
>/dev/null - Redirect standard output to nothing, basically disabling it.
2>&1 - Redirect standard error(2) output to standard output(1), which is redirected to null
& - detach to background, this will redirect standard input also to /dev/null.
This is essentially exactly what start-stop-daemon utility from Debian dpkg does at its core. That is why I prefer starting scripts in this way rather then introducing another external utility call in my code. start-stop-daemon is useful in cases where you have full blown daemon programs that you need to start and where you then need additional functionality that start-stop-daemon provides (for example checking if the specified process is already running so that it doesn't launch it again).
It is also worth noting that you can also close file descriptors of your process instead of redirecting them to /dev/null, for example:
0<&- Close standard input(0)
1>&- Close standard output(1)
2>&- Close standard error(2) output
The direction of < > signs does not matter as long file descriptor number is specified. So this is equally good:
or
However there is a bit shorter way to write that, without numbers for stdin and stdout, where direction does matter:
When the file descriptors are either closed or redirected to /dev/null (start-stop-daemon is doing the redirection to /dev/null) the process is safe to run in background as a daemon. So that is what is needed to avoid problems(startpar) with launching scripts during boot time.
I've implemented the whole solution from my initial idea and placed it on GitHub:
https://github.com/ivankovacevic/userspaceServices
You can use the start-stop-daemon out of init.d with the
--user
option.I haven't fully tested this, but I think that something like:
at startup and then
when shutting down.
Handling the .shutDown script could be done by something like the startup thing, but you cant be sure that the scripts run to end since shutdown should happen anyway :-)
should do the trick, perhaps you should throw in some input redirection, but then you would have to worry about log files being filled.
Have you tried using
su
?-c
tells su to execute the command, and the last parameter is the user to execute it as.