Londoner
Londoner

Reputation: 23

Error when running a script (with a while Loop) in a script created background process

Is it possible to use a while loop in a background job created by a script? This works perfectly fine when I manually run this in command prompt.

Called Script Content (test.sh)

#!/bin/bash
> switch
echo 'Running' >> switch
check=$(more switch)
echo $check 

while [ $check = 'Running' ]
do
sleep 5s    
check=$(more switch)
    echo $check  
done

Calling Script Content (start.sh)

#!/bin/bash
$PWD/test.sh &

I am getting an error:

-bash: [: too many arguments

when the calling script runs. The called script run manually without issue. Is while loop not allow in a script created background job?

Upvotes: 2

Views: 480

Answers (3)

echo 'Running' >> swtich
check=$(more switch) 

You write to a file called swtich and then read to a file called switch. That file doesn't exist, so the variable check ends up empty.

Incidentally, why call more? That's only useful to view a file page by page. If you're piping the output, cat is equivalent. If more doesn't have a controlling terminal, which happens when you call test.sh in the background, more prints an extra line containing the file name, so its output

So you really must use cat and not more. (In bash, you can also write check=$(<switch).)

[ $check = 'Running' ]

Since $check is empty, the command [ receives three arguments: =, Running and ]. This is not valid syntax for the [ command.

Always put double quotes around variable substitution and command substitution: "$check", "$(somecommand)". If a $ substitution occurs outside quotes, the result is split into separate words (0 words in your case, since the result was empty) and the words are interpreted as file glob patterns. This is almost never desirable, so always use double quotes unless you really have a list of glob patterns.

check=$(cat switch) is actually safe, because in an assignment, a single word is expected on the right-hand side, so word splitting doesn't happen. However, you might as well write check="$(cat switch)" for clarity. Also, the quotes are required if you write export check="$(cat switch)".

So we have:

#!/bin/bash
echo 'Running' >> switch
check=$(cat switch)

while [ "$check" = 'Running' ]
do
  sleep 5s
  check=$(cat switch)
done

In bash (but not in sh), you can write [[ $check = Running ]] instead of [ $check = Running ]. That's because [[ … ]] is special syntax, unlike [ which is a built-in command with no special parsing. However, you would need double quotes if the variable was on the right-hand side of the = operator, because the right-hand side of = inside [[ … ]] is a pattern. Rather than learn such complicated rules, just use double quotes all the time and you'll be fine.

Upvotes: 2

user000001
user000001

Reputation: 33387

The problem is basically that you haven't quoted the argument in the test command. It should be

while [ "$check" = 'Running' ]

with double quotes around the variable. If you do that, you will notice that you have a typo in the first line. Instead of

echo 'Running' >> swtich

it should be

echo 'Running' >> switch

Then it should work as expected

As a side note, it is better not to use the more command to read the contents of the file, since it is intended for humans, but instead to just do:

check=$(<switch) 

Upvotes: 0

Srini V
Srini V

Reputation: 11375

Try this:

nohup yourprogram >>/dev/null 2>>/dev/null &

Your program content should not have & or nohup

Upvotes: 0

Related Questions