0

I am writing a Bash file to execute two PhantomJS tasks.

I have two tasks written in external JS files: task1.js & task2.js.

Here's my Bash script so far:

#!/bin/bash

url=$1

cd $(cd $(dirname ${BASH_SOURCE}); pwd -P)

dir=../temp
mkdir -p $dir
file=$dir/file.txt
phantomjs "taks1.js" $url > $file

while IFS="" read -r line || [[ -n $line ]]; do
    dir=../build
    file=$dir/$line.html
    mkdir -p $(dirname $file)
    phantomjs "task2.js" $url $line > $file
done < $file

For some unknown reason task2 is being run only once, then the script stops.

If I remove the PhantomJS command, the while loop runs normally until all lines are read from the file.

Maybe someone knows why is that?

Cheers.

Julius
  • 2,473
  • 3
  • 20
  • 26
  • 2
  • BTW, run your code through http://shellcheck.net/ -- it's got a bunch of quoting bugs and such. – Charles Duffy May 11 '16 at 16:24
  • Julius: *Does* task2.js read from stdin? That would seem like odd behaviour for a phantomjs script, but it could also explain what's going on, as @Charles suggests in his comment. – rici May 11 '16 at 16:28
  • Thanks guys, for the answer and for spell checking link. The task2.js takes two passed arguments and uses them to retrieve the HTML page, reads the content and outputs to a console, which then is saved to a file by a script. – Julius May 11 '16 at 16:36
  • ...I've also amended into my answer a suggestion that avoids the need for a temporary file entirely. – Charles Duffy May 11 '16 at 16:51
  • Brilliant, thanks! I owe you a pint :D – Julius May 11 '16 at 17:14
  • One last thing. Can I set a limit for a PhantomJS task so it's killed if not responded in let's say 15 seconds? I want to put this as a cron task. – Julius May 11 '16 at 17:20
  • Yes -- that's a separate question, also covered in BashFAQ #68: http://mywiki.wooledge.org/BashFAQ/068 – Charles Duffy May 11 '16 at 19:22

1 Answers1

4

Your loop is reading contents from stdin. If any other program you run consumes stdin, the loop will terminate.

Either fix any program that may be consuming stdin to read from /dev/null, or use a different FD for the loop.

The first approach looks like this:

phantomjs "task2.js" "$url" "$line" >"$file" </dev/null

The second looks like this (note the 3< on establishing the redirection, and the <&3 to read from that file descriptor):

while IFS="" read -r line <&3 || [[ -n $line ]]; do
    dir=../build
    file=$dir/$line.html
    mkdir -p "$(dirname "$file")"
    phantomjs "task2.js" "$url" "$line" >"$file"
done 3< $file

By the way, consider taking file out of the loop altogether, by having the loop read directly from the first phantomjs program's output:

while IFS="" read -r line <&3 || [[ -n $line ]]; do
    dir=../build
    file=$dir/$line.html
    mkdir -p "$(dirname "$file")"
    phantomjs "task2.js" "$url" "$line" >"$file"
done 3< <(phantomjs "task1.js" "$url")
Charles Duffy
  • 280,126
  • 43
  • 390
  • 441