Shell Script while loop: [ around a pipeline missing `]'
The shell script I'm trying to use keeps giving this error:
$ ./script.sh: line 2: [: missing `]'
grep: ]: No such file or directory
The line is part of a section trying to check if a particular process is going to have a file locked:
COUNTER=0
while [ ps aux | grep "[r]elayevent.sh" ] && [ "$COUNTER" -lt 10 ]; do
sleep 3
let COUNTER+=1
done
Obviously I've checked that the brackets all pair up correctly - which looks fine to me. Also the common white space around the condition issue doesn't apply.
What am I missing here?
linux shell-script scripting
add a comment |
The shell script I'm trying to use keeps giving this error:
$ ./script.sh: line 2: [: missing `]'
grep: ]: No such file or directory
The line is part of a section trying to check if a particular process is going to have a file locked:
COUNTER=0
while [ ps aux | grep "[r]elayevent.sh" ] && [ "$COUNTER" -lt 10 ]; do
sleep 3
let COUNTER+=1
done
Obviously I've checked that the brackets all pair up correctly - which looks fine to me. Also the common white space around the condition issue doesn't apply.
What am I missing here?
linux shell-script scripting
2
Note for the future. Whenever you get a syntax error, run - don't walk - straight to shellcheck.net and paste in the block of your code that exhibits the issue.
– roaima
Feb 6 at 8:37
You should useflockcommand to implement locks in scripts.
– dnt
Feb 6 at 10:03
add a comment |
The shell script I'm trying to use keeps giving this error:
$ ./script.sh: line 2: [: missing `]'
grep: ]: No such file or directory
The line is part of a section trying to check if a particular process is going to have a file locked:
COUNTER=0
while [ ps aux | grep "[r]elayevent.sh" ] && [ "$COUNTER" -lt 10 ]; do
sleep 3
let COUNTER+=1
done
Obviously I've checked that the brackets all pair up correctly - which looks fine to me. Also the common white space around the condition issue doesn't apply.
What am I missing here?
linux shell-script scripting
The shell script I'm trying to use keeps giving this error:
$ ./script.sh: line 2: [: missing `]'
grep: ]: No such file or directory
The line is part of a section trying to check if a particular process is going to have a file locked:
COUNTER=0
while [ ps aux | grep "[r]elayevent.sh" ] && [ "$COUNTER" -lt 10 ]; do
sleep 3
let COUNTER+=1
done
Obviously I've checked that the brackets all pair up correctly - which looks fine to me. Also the common white space around the condition issue doesn't apply.
What am I missing here?
linux shell-script scripting
linux shell-script scripting
edited 20 hours ago
PRY
2,23031025
2,23031025
asked Feb 6 at 3:32
Kiwi CamKiwi Cam
293
293
2
Note for the future. Whenever you get a syntax error, run - don't walk - straight to shellcheck.net and paste in the block of your code that exhibits the issue.
– roaima
Feb 6 at 8:37
You should useflockcommand to implement locks in scripts.
– dnt
Feb 6 at 10:03
add a comment |
2
Note for the future. Whenever you get a syntax error, run - don't walk - straight to shellcheck.net and paste in the block of your code that exhibits the issue.
– roaima
Feb 6 at 8:37
You should useflockcommand to implement locks in scripts.
– dnt
Feb 6 at 10:03
2
2
Note for the future. Whenever you get a syntax error, run - don't walk - straight to shellcheck.net and paste in the block of your code that exhibits the issue.
– roaima
Feb 6 at 8:37
Note for the future. Whenever you get a syntax error, run - don't walk - straight to shellcheck.net and paste in the block of your code that exhibits the issue.
– roaima
Feb 6 at 8:37
You should use
flock command to implement locks in scripts.– dnt
Feb 6 at 10:03
You should use
flock command to implement locks in scripts.– dnt
Feb 6 at 10:03
add a comment |
2 Answers
2
active
oldest
votes
The error is that you should remove first [ because of you want to check the exit status then use command directly.
The Wiki pages of the Shellcheck tool have an explanation for this (issue SC1014):
[ .. ]is not part of shell syntax likeifstatements. It is not equivalent to parentheses in C-like languages,if (foo) { bar; }, and should not be wrapped around commands to test.
[is just regular command, likewhoamiorgrep, but with a funny name (seels -l /bin/[). It's a shorthand fortest.
If you want to check the exit status of a certain command, use that command directly.
If you want to check the output of a command, use
"$(..)"to get its output, and then usetestor[/[[to do a string comparison:
Also use ps aux | grep -q "[r]elayevent.sh" so that you will get the exit status silently instead of printing anything to stdout.
Or you can use pgrep and direct it's output to /dev/null.
Use second condition first because it will be more efficient for the last case.
So final script will be like:
#!/bin/bash
COUNTER=0
while [ "$COUNTER" -lt 10 ] && ps aux | grep -q "[r]elayevent.sh" ; do
sleep 3
let COUNTER+=1
done
Or
#!/bin/bash
COUNTER=0
while [ "$COUNTER" -lt 10 ] && pgrep "[r]elayevent.sh" >/dev/null ; do
sleep 3
let COUNTER+=1
done
4
You probably want to add-qwhen callinggrep, too. Otherwise it prints the matching lines.
– Mikel
Feb 6 at 4:21
@Mikel thanks, it will silently give status instead of printing anything.
– PRY
Feb 6 at 4:25
You should mention where that quote is from. Also,grep -q "[r]elayevent.sh"doesn't make much sense, andps | grepis usually better replaced withpgrep; but thelet COUNTER+=1is fine inbash,zshandksh39(((..))is not a bit more portable) -- though the whole script doesn't make much sense ;-)).
– mosvy
Feb 6 at 4:59
1
I would swap the tests around to avoid runninggrepon the last iteration.
– Kusalananda
Feb 6 at 7:31
That is more efficient.
– PRY
Feb 6 at 7:49
|
show 1 more comment
You can't have a pipe inside [ ... ]. It's also better to use pgrep than to try to parse the output of ps:
count=0
while [ "$count" -lt 10 ] && pgrep relayevent.sh >/dev/null; then
sleep 3
count=$(( count + 1 ))
done
BSD systems could use pgrep -q ... instead of pgrep ... >/dev/null to discard the actual output of pgrep, just as with ordinary grep (we're only interested in the exit status).
Note how we don't put the pgrep command within [ ... ]. That's because we're not interested in its output, only its exit status. With [ ... ] you commonly compare strings or numbers. The [ ... ] will result in an exit status that is zero (true) or non-zero (false), just like the pgrep execution.
However, this does not check for any locking mechanisms, only whether a particular process is running or not.
If you are trying to get only a single instance of a script running, then it's better to do something like this (assuming the EXIT trap is executed whenever the script is terminating orderly):
lockdir=dir.lock
if mkdir "$lockdir"; then
trap 'rmdir "$lockdir"' EXIT
else
echo 'Only one instance of this script allowed' >&2
exit 1
fi
With a number of tries and sleep:
lockdir=dir.lock
count=0
while [ "$count" -lt 10 ]; then
if mkdir "$lockdir"; then
trap 'rmdir "$lockdir"' EXIT
break
else
echo 'Locked. Sleeping...' >&2
sleep 3
fi
count=$(( count + 1 ))
done
if [ "$count" -eq 10 ]; then
echo 'Giving up.' >&2
exit 1
fi
Related:
- How to make sure only one instance of a bash script runs?
I also thought of pgrep but didn't thought of/dev/null.
– PRY
Feb 6 at 8:43
@PRYpgrepon BSD systems have a-qoption to avoid that particular ugliness. It works just as withgrep.
– Kusalananda
Feb 6 at 8:46
@PRY you could usepkill -0 ...instead ofpgrep ... >/dev/null
– Uncle Billy
Feb 6 at 8:46
add a comment |
Your Answer
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "106"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f498953%2fshell-script-while-loop-around-a-pipeline-missing%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
The error is that you should remove first [ because of you want to check the exit status then use command directly.
The Wiki pages of the Shellcheck tool have an explanation for this (issue SC1014):
[ .. ]is not part of shell syntax likeifstatements. It is not equivalent to parentheses in C-like languages,if (foo) { bar; }, and should not be wrapped around commands to test.
[is just regular command, likewhoamiorgrep, but with a funny name (seels -l /bin/[). It's a shorthand fortest.
If you want to check the exit status of a certain command, use that command directly.
If you want to check the output of a command, use
"$(..)"to get its output, and then usetestor[/[[to do a string comparison:
Also use ps aux | grep -q "[r]elayevent.sh" so that you will get the exit status silently instead of printing anything to stdout.
Or you can use pgrep and direct it's output to /dev/null.
Use second condition first because it will be more efficient for the last case.
So final script will be like:
#!/bin/bash
COUNTER=0
while [ "$COUNTER" -lt 10 ] && ps aux | grep -q "[r]elayevent.sh" ; do
sleep 3
let COUNTER+=1
done
Or
#!/bin/bash
COUNTER=0
while [ "$COUNTER" -lt 10 ] && pgrep "[r]elayevent.sh" >/dev/null ; do
sleep 3
let COUNTER+=1
done
4
You probably want to add-qwhen callinggrep, too. Otherwise it prints the matching lines.
– Mikel
Feb 6 at 4:21
@Mikel thanks, it will silently give status instead of printing anything.
– PRY
Feb 6 at 4:25
You should mention where that quote is from. Also,grep -q "[r]elayevent.sh"doesn't make much sense, andps | grepis usually better replaced withpgrep; but thelet COUNTER+=1is fine inbash,zshandksh39(((..))is not a bit more portable) -- though the whole script doesn't make much sense ;-)).
– mosvy
Feb 6 at 4:59
1
I would swap the tests around to avoid runninggrepon the last iteration.
– Kusalananda
Feb 6 at 7:31
That is more efficient.
– PRY
Feb 6 at 7:49
|
show 1 more comment
The error is that you should remove first [ because of you want to check the exit status then use command directly.
The Wiki pages of the Shellcheck tool have an explanation for this (issue SC1014):
[ .. ]is not part of shell syntax likeifstatements. It is not equivalent to parentheses in C-like languages,if (foo) { bar; }, and should not be wrapped around commands to test.
[is just regular command, likewhoamiorgrep, but with a funny name (seels -l /bin/[). It's a shorthand fortest.
If you want to check the exit status of a certain command, use that command directly.
If you want to check the output of a command, use
"$(..)"to get its output, and then usetestor[/[[to do a string comparison:
Also use ps aux | grep -q "[r]elayevent.sh" so that you will get the exit status silently instead of printing anything to stdout.
Or you can use pgrep and direct it's output to /dev/null.
Use second condition first because it will be more efficient for the last case.
So final script will be like:
#!/bin/bash
COUNTER=0
while [ "$COUNTER" -lt 10 ] && ps aux | grep -q "[r]elayevent.sh" ; do
sleep 3
let COUNTER+=1
done
Or
#!/bin/bash
COUNTER=0
while [ "$COUNTER" -lt 10 ] && pgrep "[r]elayevent.sh" >/dev/null ; do
sleep 3
let COUNTER+=1
done
4
You probably want to add-qwhen callinggrep, too. Otherwise it prints the matching lines.
– Mikel
Feb 6 at 4:21
@Mikel thanks, it will silently give status instead of printing anything.
– PRY
Feb 6 at 4:25
You should mention where that quote is from. Also,grep -q "[r]elayevent.sh"doesn't make much sense, andps | grepis usually better replaced withpgrep; but thelet COUNTER+=1is fine inbash,zshandksh39(((..))is not a bit more portable) -- though the whole script doesn't make much sense ;-)).
– mosvy
Feb 6 at 4:59
1
I would swap the tests around to avoid runninggrepon the last iteration.
– Kusalananda
Feb 6 at 7:31
That is more efficient.
– PRY
Feb 6 at 7:49
|
show 1 more comment
The error is that you should remove first [ because of you want to check the exit status then use command directly.
The Wiki pages of the Shellcheck tool have an explanation for this (issue SC1014):
[ .. ]is not part of shell syntax likeifstatements. It is not equivalent to parentheses in C-like languages,if (foo) { bar; }, and should not be wrapped around commands to test.
[is just regular command, likewhoamiorgrep, but with a funny name (seels -l /bin/[). It's a shorthand fortest.
If you want to check the exit status of a certain command, use that command directly.
If you want to check the output of a command, use
"$(..)"to get its output, and then usetestor[/[[to do a string comparison:
Also use ps aux | grep -q "[r]elayevent.sh" so that you will get the exit status silently instead of printing anything to stdout.
Or you can use pgrep and direct it's output to /dev/null.
Use second condition first because it will be more efficient for the last case.
So final script will be like:
#!/bin/bash
COUNTER=0
while [ "$COUNTER" -lt 10 ] && ps aux | grep -q "[r]elayevent.sh" ; do
sleep 3
let COUNTER+=1
done
Or
#!/bin/bash
COUNTER=0
while [ "$COUNTER" -lt 10 ] && pgrep "[r]elayevent.sh" >/dev/null ; do
sleep 3
let COUNTER+=1
done
The error is that you should remove first [ because of you want to check the exit status then use command directly.
The Wiki pages of the Shellcheck tool have an explanation for this (issue SC1014):
[ .. ]is not part of shell syntax likeifstatements. It is not equivalent to parentheses in C-like languages,if (foo) { bar; }, and should not be wrapped around commands to test.
[is just regular command, likewhoamiorgrep, but with a funny name (seels -l /bin/[). It's a shorthand fortest.
If you want to check the exit status of a certain command, use that command directly.
If you want to check the output of a command, use
"$(..)"to get its output, and then usetestor[/[[to do a string comparison:
Also use ps aux | grep -q "[r]elayevent.sh" so that you will get the exit status silently instead of printing anything to stdout.
Or you can use pgrep and direct it's output to /dev/null.
Use second condition first because it will be more efficient for the last case.
So final script will be like:
#!/bin/bash
COUNTER=0
while [ "$COUNTER" -lt 10 ] && ps aux | grep -q "[r]elayevent.sh" ; do
sleep 3
let COUNTER+=1
done
Or
#!/bin/bash
COUNTER=0
while [ "$COUNTER" -lt 10 ] && pgrep "[r]elayevent.sh" >/dev/null ; do
sleep 3
let COUNTER+=1
done
edited Feb 6 at 13:28
ilkkachu
58.7k892165
58.7k892165
answered Feb 6 at 4:02
PRYPRY
2,23031025
2,23031025
4
You probably want to add-qwhen callinggrep, too. Otherwise it prints the matching lines.
– Mikel
Feb 6 at 4:21
@Mikel thanks, it will silently give status instead of printing anything.
– PRY
Feb 6 at 4:25
You should mention where that quote is from. Also,grep -q "[r]elayevent.sh"doesn't make much sense, andps | grepis usually better replaced withpgrep; but thelet COUNTER+=1is fine inbash,zshandksh39(((..))is not a bit more portable) -- though the whole script doesn't make much sense ;-)).
– mosvy
Feb 6 at 4:59
1
I would swap the tests around to avoid runninggrepon the last iteration.
– Kusalananda
Feb 6 at 7:31
That is more efficient.
– PRY
Feb 6 at 7:49
|
show 1 more comment
4
You probably want to add-qwhen callinggrep, too. Otherwise it prints the matching lines.
– Mikel
Feb 6 at 4:21
@Mikel thanks, it will silently give status instead of printing anything.
– PRY
Feb 6 at 4:25
You should mention where that quote is from. Also,grep -q "[r]elayevent.sh"doesn't make much sense, andps | grepis usually better replaced withpgrep; but thelet COUNTER+=1is fine inbash,zshandksh39(((..))is not a bit more portable) -- though the whole script doesn't make much sense ;-)).
– mosvy
Feb 6 at 4:59
1
I would swap the tests around to avoid runninggrepon the last iteration.
– Kusalananda
Feb 6 at 7:31
That is more efficient.
– PRY
Feb 6 at 7:49
4
4
You probably want to add
-q when calling grep, too. Otherwise it prints the matching lines.– Mikel
Feb 6 at 4:21
You probably want to add
-q when calling grep, too. Otherwise it prints the matching lines.– Mikel
Feb 6 at 4:21
@Mikel thanks, it will silently give status instead of printing anything.
– PRY
Feb 6 at 4:25
@Mikel thanks, it will silently give status instead of printing anything.
– PRY
Feb 6 at 4:25
You should mention where that quote is from. Also,
grep -q "[r]elayevent.sh" doesn't make much sense, and ps | grep is usually better replaced with pgrep; but the let COUNTER+=1 is fine in bash, zsh and ksh39 (((..)) is not a bit more portable) -- though the whole script doesn't make much sense ;-)).– mosvy
Feb 6 at 4:59
You should mention where that quote is from. Also,
grep -q "[r]elayevent.sh" doesn't make much sense, and ps | grep is usually better replaced with pgrep; but the let COUNTER+=1 is fine in bash, zsh and ksh39 (((..)) is not a bit more portable) -- though the whole script doesn't make much sense ;-)).– mosvy
Feb 6 at 4:59
1
1
I would swap the tests around to avoid running
grep on the last iteration.– Kusalananda
Feb 6 at 7:31
I would swap the tests around to avoid running
grep on the last iteration.– Kusalananda
Feb 6 at 7:31
That is more efficient.
– PRY
Feb 6 at 7:49
That is more efficient.
– PRY
Feb 6 at 7:49
|
show 1 more comment
You can't have a pipe inside [ ... ]. It's also better to use pgrep than to try to parse the output of ps:
count=0
while [ "$count" -lt 10 ] && pgrep relayevent.sh >/dev/null; then
sleep 3
count=$(( count + 1 ))
done
BSD systems could use pgrep -q ... instead of pgrep ... >/dev/null to discard the actual output of pgrep, just as with ordinary grep (we're only interested in the exit status).
Note how we don't put the pgrep command within [ ... ]. That's because we're not interested in its output, only its exit status. With [ ... ] you commonly compare strings or numbers. The [ ... ] will result in an exit status that is zero (true) or non-zero (false), just like the pgrep execution.
However, this does not check for any locking mechanisms, only whether a particular process is running or not.
If you are trying to get only a single instance of a script running, then it's better to do something like this (assuming the EXIT trap is executed whenever the script is terminating orderly):
lockdir=dir.lock
if mkdir "$lockdir"; then
trap 'rmdir "$lockdir"' EXIT
else
echo 'Only one instance of this script allowed' >&2
exit 1
fi
With a number of tries and sleep:
lockdir=dir.lock
count=0
while [ "$count" -lt 10 ]; then
if mkdir "$lockdir"; then
trap 'rmdir "$lockdir"' EXIT
break
else
echo 'Locked. Sleeping...' >&2
sleep 3
fi
count=$(( count + 1 ))
done
if [ "$count" -eq 10 ]; then
echo 'Giving up.' >&2
exit 1
fi
Related:
- How to make sure only one instance of a bash script runs?
I also thought of pgrep but didn't thought of/dev/null.
– PRY
Feb 6 at 8:43
@PRYpgrepon BSD systems have a-qoption to avoid that particular ugliness. It works just as withgrep.
– Kusalananda
Feb 6 at 8:46
@PRY you could usepkill -0 ...instead ofpgrep ... >/dev/null
– Uncle Billy
Feb 6 at 8:46
add a comment |
You can't have a pipe inside [ ... ]. It's also better to use pgrep than to try to parse the output of ps:
count=0
while [ "$count" -lt 10 ] && pgrep relayevent.sh >/dev/null; then
sleep 3
count=$(( count + 1 ))
done
BSD systems could use pgrep -q ... instead of pgrep ... >/dev/null to discard the actual output of pgrep, just as with ordinary grep (we're only interested in the exit status).
Note how we don't put the pgrep command within [ ... ]. That's because we're not interested in its output, only its exit status. With [ ... ] you commonly compare strings or numbers. The [ ... ] will result in an exit status that is zero (true) or non-zero (false), just like the pgrep execution.
However, this does not check for any locking mechanisms, only whether a particular process is running or not.
If you are trying to get only a single instance of a script running, then it's better to do something like this (assuming the EXIT trap is executed whenever the script is terminating orderly):
lockdir=dir.lock
if mkdir "$lockdir"; then
trap 'rmdir "$lockdir"' EXIT
else
echo 'Only one instance of this script allowed' >&2
exit 1
fi
With a number of tries and sleep:
lockdir=dir.lock
count=0
while [ "$count" -lt 10 ]; then
if mkdir "$lockdir"; then
trap 'rmdir "$lockdir"' EXIT
break
else
echo 'Locked. Sleeping...' >&2
sleep 3
fi
count=$(( count + 1 ))
done
if [ "$count" -eq 10 ]; then
echo 'Giving up.' >&2
exit 1
fi
Related:
- How to make sure only one instance of a bash script runs?
I also thought of pgrep but didn't thought of/dev/null.
– PRY
Feb 6 at 8:43
@PRYpgrepon BSD systems have a-qoption to avoid that particular ugliness. It works just as withgrep.
– Kusalananda
Feb 6 at 8:46
@PRY you could usepkill -0 ...instead ofpgrep ... >/dev/null
– Uncle Billy
Feb 6 at 8:46
add a comment |
You can't have a pipe inside [ ... ]. It's also better to use pgrep than to try to parse the output of ps:
count=0
while [ "$count" -lt 10 ] && pgrep relayevent.sh >/dev/null; then
sleep 3
count=$(( count + 1 ))
done
BSD systems could use pgrep -q ... instead of pgrep ... >/dev/null to discard the actual output of pgrep, just as with ordinary grep (we're only interested in the exit status).
Note how we don't put the pgrep command within [ ... ]. That's because we're not interested in its output, only its exit status. With [ ... ] you commonly compare strings or numbers. The [ ... ] will result in an exit status that is zero (true) or non-zero (false), just like the pgrep execution.
However, this does not check for any locking mechanisms, only whether a particular process is running or not.
If you are trying to get only a single instance of a script running, then it's better to do something like this (assuming the EXIT trap is executed whenever the script is terminating orderly):
lockdir=dir.lock
if mkdir "$lockdir"; then
trap 'rmdir "$lockdir"' EXIT
else
echo 'Only one instance of this script allowed' >&2
exit 1
fi
With a number of tries and sleep:
lockdir=dir.lock
count=0
while [ "$count" -lt 10 ]; then
if mkdir "$lockdir"; then
trap 'rmdir "$lockdir"' EXIT
break
else
echo 'Locked. Sleeping...' >&2
sleep 3
fi
count=$(( count + 1 ))
done
if [ "$count" -eq 10 ]; then
echo 'Giving up.' >&2
exit 1
fi
Related:
- How to make sure only one instance of a bash script runs?
You can't have a pipe inside [ ... ]. It's also better to use pgrep than to try to parse the output of ps:
count=0
while [ "$count" -lt 10 ] && pgrep relayevent.sh >/dev/null; then
sleep 3
count=$(( count + 1 ))
done
BSD systems could use pgrep -q ... instead of pgrep ... >/dev/null to discard the actual output of pgrep, just as with ordinary grep (we're only interested in the exit status).
Note how we don't put the pgrep command within [ ... ]. That's because we're not interested in its output, only its exit status. With [ ... ] you commonly compare strings or numbers. The [ ... ] will result in an exit status that is zero (true) or non-zero (false), just like the pgrep execution.
However, this does not check for any locking mechanisms, only whether a particular process is running or not.
If you are trying to get only a single instance of a script running, then it's better to do something like this (assuming the EXIT trap is executed whenever the script is terminating orderly):
lockdir=dir.lock
if mkdir "$lockdir"; then
trap 'rmdir "$lockdir"' EXIT
else
echo 'Only one instance of this script allowed' >&2
exit 1
fi
With a number of tries and sleep:
lockdir=dir.lock
count=0
while [ "$count" -lt 10 ]; then
if mkdir "$lockdir"; then
trap 'rmdir "$lockdir"' EXIT
break
else
echo 'Locked. Sleeping...' >&2
sleep 3
fi
count=$(( count + 1 ))
done
if [ "$count" -eq 10 ]; then
echo 'Giving up.' >&2
exit 1
fi
Related:
- How to make sure only one instance of a bash script runs?
edited Feb 7 at 8:31
answered Feb 6 at 8:05
KusalanandaKusalananda
129k16246404
129k16246404
I also thought of pgrep but didn't thought of/dev/null.
– PRY
Feb 6 at 8:43
@PRYpgrepon BSD systems have a-qoption to avoid that particular ugliness. It works just as withgrep.
– Kusalananda
Feb 6 at 8:46
@PRY you could usepkill -0 ...instead ofpgrep ... >/dev/null
– Uncle Billy
Feb 6 at 8:46
add a comment |
I also thought of pgrep but didn't thought of/dev/null.
– PRY
Feb 6 at 8:43
@PRYpgrepon BSD systems have a-qoption to avoid that particular ugliness. It works just as withgrep.
– Kusalananda
Feb 6 at 8:46
@PRY you could usepkill -0 ...instead ofpgrep ... >/dev/null
– Uncle Billy
Feb 6 at 8:46
I also thought of pgrep but didn't thought of
/dev/null.– PRY
Feb 6 at 8:43
I also thought of pgrep but didn't thought of
/dev/null.– PRY
Feb 6 at 8:43
@PRY
pgrep on BSD systems have a -q option to avoid that particular ugliness. It works just as with grep.– Kusalananda
Feb 6 at 8:46
@PRY
pgrep on BSD systems have a -q option to avoid that particular ugliness. It works just as with grep.– Kusalananda
Feb 6 at 8:46
@PRY you could use
pkill -0 ... instead of pgrep ... >/dev/null– Uncle Billy
Feb 6 at 8:46
@PRY you could use
pkill -0 ... instead of pgrep ... >/dev/null– Uncle Billy
Feb 6 at 8:46
add a comment |
Thanks for contributing an answer to Unix & Linux Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f498953%2fshell-script-while-loop-around-a-pipeline-missing%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
2
Note for the future. Whenever you get a syntax error, run - don't walk - straight to shellcheck.net and paste in the block of your code that exhibits the issue.
– roaima
Feb 6 at 8:37
You should use
flockcommand to implement locks in scripts.– dnt
Feb 6 at 10:03