I'm attempting to run a few commands that never finish. These commands watch a directory and update files when they change. The idea is that I need multiple folders watched by different tools, able to run all of them from a single command.

For normal commands that return as expected, separating the commands with a ; works.

ls /;
cd /;
ls var;
cd var;
ls log;
cd log

When I attempt to chain together non-returning commands (like tail -f <some_file> or coffee -c -w <some_coffeescript_folder>, only the first command will run.

Is there a way of doing this in a single command? Here's the commands I'm trying to link together:

coffee -c -m -w public/javascript/*.coffee; \
stylus views/stylesheets/*.styl -w -m --out public/stylesheets/; \
stylus views/stylesheets/lib/*.styl -w -m --out public/stylesheets/lib/;
  • What do you mean by "one after another" if the first one never finishes? When do you want the second one to start? Oct 27 '14 at 20:47
  • @HenningMakholm The first one won't finish. I just want all of them to run. I suppose sequentially isn't actually true here, parallel would be more accurate. I've updated the question. Oct 27 '14 at 20:49

You can run them in background by adding an ampersand to the command:

coffee -c -m -w public/javascript/*.coffee &
stylus views/stylesheets/*.styl -w -m --out public/stylesheets/ &
stylus views/stylesheets/lib/*.styl -w -m --out public/stylesheets/lib/ &

If you want to see all jobs currently running in the background do a:

jobs -l

To get a background job back into foreground, use fg (PID is optional):

fg <PID>

To send a foreground job (which "blocks" your shell) back into background mode use Ctrl-Z / bg:

$ tail -f foobar.log # is "blocking" your shell
(hit Ctrl-Z)
$ bg

I guess the jobs are bound to your shell and will not fork automatically. This means if you're logged in via SSH and you disconnect, the shell receives a SIGHUP, which will be sent to the jobs as well. This will stop/exit your commands.

If you want to keep the jobs up&running even after you've logged out, you might want look into the bash built-in "disown":

jobs               # fetch job ID in the squre brackets
disown -h %<JOBID> # disown job by using the job ID

Another option is "nohup" (command, not a bash built-in) or you use a terminal multiplexer like "screen" or "tmux".

  • Holy... Great answer, thanks a ton! I'm actually setting these commands up in a horribly butchered Makefile, but there's a lot of info I didn't know about here. Thank you very much for your detailed answer! Oct 28 '14 at 7:20
  • btw if you want to "watch" a directory or file, have a look into inotify and the command-line inotify-tools github.com/rvoicilas/inotify-tools/wiki Oct 28 '14 at 7:20

Try this:

coffee -c -m -w public/javascript/*.coffee &
stylus views/stylesheets/*.styl -w -m --out public/stylesheets/ &
stylus views/stylesheets/lib/*.styl -w -m --out public/stylesheets/lib/ &
  • I actually tried this, but I had an extra ; after the ampersand. Thanks! Oct 27 '14 at 21:01

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.