6

When I type the following in my terminal running zsh (each line is a command)

babel www/scripts6/lib/data.js > www/scripts/lib/data.js &
babel www/scripts6/lib/user.js > www/scripts/lib/user.js &
babel www/scripts6/lib/profile.js > www/scripts/lib/profile.js &
babel www/scripts6/lib/d3-and-svg.js > www/scripts/lib/d3-and-svg.js &
babel www/scripts6/main.js > www/scripts/main.js &
while [[ $(jobs) =~ 'babel' ]]; do echo 'moo'; done

it moos for about 3 seconds and then stops. But when I put the same exact code in the file moo.zsh and then run it in my terminal with

zsh moo.zsh

it completes in less than 1 second and doesn't moo at all. Why did it happen?

  • moo moo moo moo – mareoraft Sep 4 '15 at 0:21
  • 2
    shells only tend to have job control turned on in interactive mode. – PSkocik Sep 4 '15 at 0:32
  • 1
    you should do the waiting with wait – PSkocik Sep 4 '15 at 0:33
  • @PSkocik make that an answer, it's correct. wait is the proper way to do this and will work both interactively and in a script. – Celada Sep 4 '15 at 1:21
  • @PSkocik Is there an easy way to turn job control on and off? – mareoraft Sep 4 '15 at 1:49
9

In non-interactive shell, you don't have full jobs control. When you start jobs in command substitution, it ran in a subshell. In this subshell, there's no jobs running, you got nothing.

In interactive shell, the MONITOR was set, gave you full jobs control. In this case, zsh store all jobs in a table when you enter a subshell, and will use that job table if there's no jobs in subshell.

With zsh 4.3 and above, you can turn on job control in non-interactive shell by putting -m on shebang line:

#!/usr/bin/zsh -m

or using setopt:

setopt monitor
: The rest of script goes here

A better way to check the job state can be:

#!/usr/bin/zsh
zmodload zsh/parameter

babel www/scripts6/lib/data.js > www/scripts/lib/data.js &
babel www/scripts6/lib/user.js > www/scripts/lib/user.js &
babel www/scripts6/lib/profile.js > www/scripts/lib/profile.js &
babel www/scripts6/lib/d3-and-svg.js > www/scripts/lib/d3-and-svg.js &
babel www/scripts6/main.js > www/scripts/main.js &

while (( ${#jobstates} )); do
  print "moo"
done

Anyway, you can wait for all child processes with builtin wait:

babel www/scripts6/lib/data.js > www/scripts/lib/data.js &
babel www/scripts6/lib/user.js > www/scripts/lib/user.js &
babel www/scripts6/lib/profile.js > www/scripts/lib/profile.js &
babel www/scripts6/lib/d3-and-svg.js > www/scripts/lib/d3-and-svg.js &
babel www/scripts6/main.js > www/scripts/main.js &
# Wait for all children
wait
echo END
  • Thank you, but the real question is about the absence of 'moo's. The accepted answer must correctly account for such phenomenon. – mareoraft Sep 4 '15 at 1:47
  • @mareoraft: I made it more details. – cuonglm Sep 4 '15 at 2:32
  • A big MOO to you sir!!! – mareoraft Sep 4 '15 at 20:18

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.