Running background process (webserver) for just as long as other process (test suite) executes - bash

I'm looking for a unix shell command that would allow me to run a process in the background (which happens to be a webserver) for just as long as another foreground process (which happens to be a test suite) executes. I.e, after the foreground process exits, the background process should exit as well. What I have so far is
.. preliminary work .. && (webserver & test)
which comes close, but fails in that the webserver process never exits. Is there a good way to express this in a single command or would it be more reasonable to write a more verbose script for that?
To give some further detail (and welcoming any relevant suggestions), I'm in the process of writing a javascript lib which I'd like to test using Selenium - hence the need for the webserver to execute 'alongside' the test suite. And in my attempt to do away with Grunt & co. and follow a leaner, npm-based approach to task management I've hit this shell-related road bump.

You can try this:
# .. preliminary work ..
webserver &
PID=$!
test_suite &
(wait $!; kill $PID)
This will work as long as you don't mind both commands being run in the background. What happens here is:
The webserver is started in the background.
The pid of it is assigned to $PID.
The test suite is started in the background.
The last line waits for the test suite to exit, and then kills the webserver.
If you need either command to be in the foreground, then run this version
# .. preliminary work ..
screen -dm -S webserver webserver
screen -dm -S test_suite test_suite
(wait "$(screen -ls | awk '/\.test_suite\t/ {print strtonum($1)}')"
screen -X -S webserver -p 0 kill) &
screen -r test_suite
Note that this requires the screen command (use apt-get install screen to install it or use ubuntu's website if you have ubuntu). What this does is:
Starts the webserver
Starts the test suite.
Waits for the test suite to exit, and then kills the webserver
In the meantime, resumes the test suite in screen

Related

How do you run a shell command in the background and suppress all output?

I'm trying to write a Shell script (for use in Mac OSX Termninal) that will run a command to start a development server (gulp serve). I have it working except the server is continuously running so it doesn't allow me to enter subsequent commands in the same window without stopping the server (Control+C). My question is, is there a way I can run the process in the background and/or suppress any/all output? My goal is to also write a 'stop server' command that will kill the process (which I'm also unsure how to do). I've tried all combinations of using ampersands and &>/dev/null and nothing quite works. Here's what I have so far:
if [ "$1" = "server" ]
then
if [ "$2" = "on" ]
then
cd / & gulp serve --gulpfile /server/example/gulpfile.js # the output is still shown
printf "\033[0;32mserver is online.\033[0m\n"
else
killall tail &>/dev/null 2>&1 # this doesn't kill the process
printf "\033[0;32mportals is offline.\033[0m\n"
fi
fi
You're doing the output redirection on killall, not gulp, so gulp will continue to merrily split out text to your terminal. Try instead:
cd / && gulp server --gulpfile /server/example/gulpfile.js >/dev/null 2>&1 &
Secondly, your kill command doesn't kill your process because you're not telling it to; you're asking it to kill all tail processes. You want instead:
killall gulp
These modifications should be the most direct path to your goal. However, there are a few additional things that may be useful to know.
Process management has a long history in the *nix world, and so we've been inventing tools to make this easier for a long time. You can go through re-inventing them yourself (the next step would be to store the PID of your gulp process so that you can ensure you only kill it and not anything else with "gulp" in the name), or you can go all the way and write a system monitoring file. For Linux, this would be SysV, Upstart, or systemd; I'm not sure what the OS X equivalent is.
However, since you're just doing this for development purposes, not a production website, you probably don't actually need that; your actual goal is to be able to execute ad-hoc shell commands while gulp is running. You can use terminal tabs to do this, or more elegantly use the splitting capabilities of iTerm, screen, or tmux. Tmux in particular is a useful tool for when you find yourself working a lot in a terminal, and would be a useful thing to become familiar with.
First, to run the process in the background
cd / && gulp serve --gulpfile /server/example/gulpfile.js > /tmp/gulp.log &
after cd you need && (and) and & to run in the background at the end.
To kill all gulp processes
killall gulp

What does "program &" mean on the command line?

I need to develop a client and server program with using sockets. My program should get port number from the command line. I saw an example which says "myprogram 2454 &".
I wonder what that & (ampersand) means there.
It means to start the process in the background. http://tldp.org/LDP/abs/html/x9644.html so that you may continue to use your shell session to run other programs. You can then use fg to "foreground" your process again.
The ampersand (&) means that you want to run myprogram in background. This is normally used when you want to stay on your command-prompt and continue the work on the same session.
Example
somescript &
will run the somescript shell script in background. You will get the prompt back on the next line. If you run somescript without & then the prompt may not appear back because somescript may take more time.
The best way is to run it in background with no hangups, in which case even of you loose your connection to the host the process keeps running on the UNIX or Linux host.
For example
nohup somescript &
the jobs command will display the jobs running in background.

Running bash script does not return to terminal when using ampersand (&) to run a subprocess in the background

I have a script (lets call it parent.sh) that makes 2 calls to a second script (child.sh) that runs a java process. The child.sh scripts are run in the background by placing an & at the end of the line in parent.sh. However, when i run parent.sh, i need to press Ctrl+C to return to the terminal screen. What is the reason for this? Is it something to do with the fact that the child.sh processes are running under the parent.sh process. So the parent.sh doesn't die until the childs do?
parent.sh
#!/bin/bash
child.sh param1a param2a &
child.sh param1b param2b &
exit 0
child.sh
#!/bin/bash
java com.test.Main
echo "Main Process Stopped" | mail -s "WARNING-Main Process is down." user#email.com
As you can see, I don't want to run the java process in the background because i want to send a mail out when the process dies. Doing it as above works fine from a functional standpoint, but i would like to know how i can get it to return to the terminal after executing parent.sh.
What i ended up doing was to make to change parent.sh to the following
#!/bin/bash
child.sh param1a param2a > startup.log &
child.sh param1b param2b > startup2.log &
exit 0
I would not have come to this solution without your suggestions and root cause analysis of the issue. Thanks!
And apologies for my inaccurate comment. (There was no input, I answered from memory and I remembered incorrectly.)
The following link from the Linux Documentation Project suggests adding a wait after your mail command in child.sh:
http://tldp.org/LDP/abs/html/x9644.html
Summary of the above document
Within a script, running a command in the background with an ampersand (&)
may cause the script to hang until ENTER is hit. This seems to occur with
commands that write to stdout. It can be a major annoyance.
....
....
As Walter Brameld IV explains it:
As far as I can tell, such scripts don't actually hang. It just
seems that they do because the background command writes text to
the console after the prompt. The user gets the impression that
the prompt was never displayed. Here's the sequence of events:
Script launches background command.
Script exits.
Shell displays the prompt.
Background command continues running and writing text to the
console.
Background command finishes.
User doesn't see a prompt at the bottom of the output, thinks script
is hanging.
If you change child.sh to look like the following you shouldn't experience this annoyance:
#!/bin/bash
java com.test.Main
echo "Main Process Stopped" | mail -s "WARNING-Main Process is down." user#gmail.com
wait
Or as #SebastianStigler states in a comment to your question above:
Add a > /dev/null at the end of the line with mail. mail will otherwise try to start its interactive mode.
This will cause the mail command to write to /dev/null rather than stdout which should also stop this annoyance.
Hope this helps
The process was still linked to the controlling terminal because STDOUT needs somewhere to go. You solved that problem by redirecting to a file ( > startup.log ).
If you're not interested in the output, discard STDOUT completely ( >/dev/null ).
If you're not interested in errors, either, discard both ( &>/dev/null ).
If you want the processes to keep running even after you log out of your terminal, use nohup — that effectively disconnects them from what you are doing and leaves them to quietly run in the background until you reboot your machine (or otherwise kill them).
nohup child.sh param1a param2a &>/dev/null &

Waiting for wine to finish running

My current script looks like this:
cd ~/.wine/drive_c/
echo "test123" > foo$$.txt
wine start "C:\foo$$.txt"
wineserver -w
echo "Wine is done!"
which works fine when only one program is running in wine at a time. However if I run this a second time, before the first program is done, both scripts will wait for each others programs to exit.
This does not work:
cd ~/.wine/drive_c/
echo "test123" > foo$$.txt
$(wine start "C:\foo$$.txt") &
wait ${!}
echo "Wine is done!"
as it will exit before you close the text editor.
I need to use the start command, because I want a file to be run with its default editor/viewer.
To wait for the process started by wine to exit, you can pipe its output to another program.
On my system, the following achieves the desired effect:
wine "program.exe" | cat
echo "program.exe has finished"
If you want to wait asynchronously:
wine "program.exe" | cat & pid=$!
# ...
wait $pid
echo "program.exe has finished"
wineserver has a --wait flag which can be used to do exactly that.
However if you run multiple programs at once, it will wait for all of them to finish.
wine <program> waits until the program exits. wine start program does not.
A summary:
wine <program> starts the program and waits until it is finished. I recommend using this method.
wine start <program> starts the program and immediately exits without waiting. The program will keep running in the background.
wine start \wait <program> starts the program and waits until it is finished. This is the same behavior as wine <program>.
wineserver --wait waits until all programs and all services in Wine are finished. This command does not launch any program itself but waits for existing programs and services.
Services like services.exe, plugplay.exe, and winedevice.exe keep on running a few seconds after the last program finishes, and wineserver --wait also waits until these services exit.
Some of these services hold state and write their state (and the registry) to disk when they exit. So if you want to backup or remove your wine prefix, make sure to wait until these services have exited.
What happens is that wine just asks wineserver to start the program and exits, and I have found no good mechanism to get notifications from wineserver about the processes that it spawns.
My suggestion would be to wait for the completion of the process started by wineserver using one of the methods in How to wait for exit of non-children processes, but you need to know its PID. Possible ideas: run wineserver -f -d | grep init_thread( and get PIDs from there, but I can see no easy way to find out which is which, to avoid race conditions, and to ignore noise; or try to find your process in the output of ps, but it's ugly, and definitely not robust.
If nothing better surfaces, you might want to suggest the addition of such a feature to the Wine devs (probably as a flag to wine).

How to automate startup of a web app with several independent processes?

I run the wesabe web app locally.
Each time I start it by opening separate shells to start the mysql server, java backend and rails frontend.
My question is, how could you automate this with a shell script or rake task?
I tried just listing the commands sequentially in a shell script (see below) but the later commands never run because each app server creates its own process that never 'returns' (until you quit the server).
I've looked into sub-shells and parallel rake tasks, but that's where I got stuck.
echo 'starting mysql'
mysqld_safe
echo 'starting pfc'
cd ~/wesabe/pfc
rails server -p 3001
echo 'starting brcm'
cd ~/wesabe/brcm-accounts-api
script/server
echo 'ok, go!'
open http://localhost:3001
If you don't mind the output being messed, put a "&" at the end of the line where you start the application to make it run in background.

Resources