How to periodically check if STDIN is open?
Clash Royale CLAN TAG#URR8PPP
Some programs will exit when their STDIN
is closed. Those that do this work nicely with Erlang/Elixir supervision via "ports".
For those that don't, the Elixir docs suggest this wrapper script:
#!/bin/bash
# wrapper.sh
"$@" &
pid=$!
while read line ; do
:
done
kill -KILL $pid
This allows calling wrapper.sh my_script arg1 arg2
. wrapper.sh
starts and backgrounds the specified program, and when wrapper.sh
's STDIN
is closed, its blocking read
finishes and it terminates the backgrounded process.
This approach has a downside, however; if the backgrounded process terminates for some other reason, wrapper.sh
doesn't notice, and therefore neither does Erlang/Elixir.
I'd like to modify this script to do the following:
In a loop:
- If
STDIN
is closed, kill$pid
- If
$pid
is dead, exit - Otherwise, sleep briefly
Can anyone suggest a way to do this?
shell file-descriptors
add a comment |
Some programs will exit when their STDIN
is closed. Those that do this work nicely with Erlang/Elixir supervision via "ports".
For those that don't, the Elixir docs suggest this wrapper script:
#!/bin/bash
# wrapper.sh
"$@" &
pid=$!
while read line ; do
:
done
kill -KILL $pid
This allows calling wrapper.sh my_script arg1 arg2
. wrapper.sh
starts and backgrounds the specified program, and when wrapper.sh
's STDIN
is closed, its blocking read
finishes and it terminates the backgrounded process.
This approach has a downside, however; if the backgrounded process terminates for some other reason, wrapper.sh
doesn't notice, and therefore neither does Erlang/Elixir.
I'd like to modify this script to do the following:
In a loop:
- If
STDIN
is closed, kill$pid
- If
$pid
is dead, exit - Otherwise, sleep briefly
Can anyone suggest a way to do this?
shell file-descriptors
add a comment |
Some programs will exit when their STDIN
is closed. Those that do this work nicely with Erlang/Elixir supervision via "ports".
For those that don't, the Elixir docs suggest this wrapper script:
#!/bin/bash
# wrapper.sh
"$@" &
pid=$!
while read line ; do
:
done
kill -KILL $pid
This allows calling wrapper.sh my_script arg1 arg2
. wrapper.sh
starts and backgrounds the specified program, and when wrapper.sh
's STDIN
is closed, its blocking read
finishes and it terminates the backgrounded process.
This approach has a downside, however; if the backgrounded process terminates for some other reason, wrapper.sh
doesn't notice, and therefore neither does Erlang/Elixir.
I'd like to modify this script to do the following:
In a loop:
- If
STDIN
is closed, kill$pid
- If
$pid
is dead, exit - Otherwise, sleep briefly
Can anyone suggest a way to do this?
shell file-descriptors
Some programs will exit when their STDIN
is closed. Those that do this work nicely with Erlang/Elixir supervision via "ports".
For those that don't, the Elixir docs suggest this wrapper script:
#!/bin/bash
# wrapper.sh
"$@" &
pid=$!
while read line ; do
:
done
kill -KILL $pid
This allows calling wrapper.sh my_script arg1 arg2
. wrapper.sh
starts and backgrounds the specified program, and when wrapper.sh
's STDIN
is closed, its blocking read
finishes and it terminates the backgrounded process.
This approach has a downside, however; if the backgrounded process terminates for some other reason, wrapper.sh
doesn't notice, and therefore neither does Erlang/Elixir.
I'd like to modify this script to do the following:
In a loop:
- If
STDIN
is closed, kill$pid
- If
$pid
is dead, exit - Otherwise, sleep briefly
Can anyone suggest a way to do this?
shell file-descriptors
shell file-descriptors
asked Jan 29 at 22:11
Nathan LongNathan Long
7881723
7881723
add a comment |
add a comment |
2 Answers
2
active
oldest
votes
You can check if $pid
is dead like so:
while kill -0 $pid >/dev/null; do
# $pid is still alive
done
# $pid is dead or you lack permissions to send signals to it
add a comment |
If your shell is dash
/busybox
, ksh93
or zsh
, you could set a trap on SIGCHLD
:
#! /bin/sh
trap exit CHLD
"$@" &
while read line; do :; done
kill $!
wait
This will exit as soon as the "$@" &
process has exited or the read
has got an EOF
.
But bash
has a nasty read
built-in, which is restarted in place when interrupted by a signal, so something clunkier is needed. You can arrange for the background process to send a terminating signal to its parent upon exiting:
#! /bin/sh
"$@"; kill $$; &
while read line; do :; done
pkill -P $!
kill $!
wait
This will have to waste another process to wait for the "$@"
command, and use the -P
(parent pid) selector of pkill
since $!
no longer refer to the "$@"
command, but to its parent. The extra kill $!
is still needed in case the "$@"
happens to be a built-in. Notice that there's no job control in scripts; all processes (including those started with &
) run in the same process group.
You can use p/kill -KILL
everywhere if a TERM
signal isn't enough.
Another, even clunkier workaround that only works with newer (>= 4.0) versions of bash is to use the nonstandard -t
(timeout) option of read
and exploit the fact that read
will return 1 upon EOF
and a status > 128 upon timeout:
#! /bin/bash
"$@" &
while :; do
read -t 1 line
case $? in
0) ;;
1) kill $!; wait; exit;;
*) kill -0 $! || exit;;
esac
done 2>/dev/null
This somehow seems to work with mksh
, too.
This is helpful! Note that the different return values forread
on timeout vsEOF
match what I see inhelp read
in Bash 5.0.2, but in Bash 3.2 there is no such distinction.
– Nathan Long
Jan 30 at 15:32
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%2f497567%2fhow-to-periodically-check-if-stdin-is-open%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
You can check if $pid
is dead like so:
while kill -0 $pid >/dev/null; do
# $pid is still alive
done
# $pid is dead or you lack permissions to send signals to it
add a comment |
You can check if $pid
is dead like so:
while kill -0 $pid >/dev/null; do
# $pid is still alive
done
# $pid is dead or you lack permissions to send signals to it
add a comment |
You can check if $pid
is dead like so:
while kill -0 $pid >/dev/null; do
# $pid is still alive
done
# $pid is dead or you lack permissions to send signals to it
You can check if $pid
is dead like so:
while kill -0 $pid >/dev/null; do
# $pid is still alive
done
# $pid is dead or you lack permissions to send signals to it
answered Jan 29 at 22:25
bitwalkerbitwalker
1311
1311
add a comment |
add a comment |
If your shell is dash
/busybox
, ksh93
or zsh
, you could set a trap on SIGCHLD
:
#! /bin/sh
trap exit CHLD
"$@" &
while read line; do :; done
kill $!
wait
This will exit as soon as the "$@" &
process has exited or the read
has got an EOF
.
But bash
has a nasty read
built-in, which is restarted in place when interrupted by a signal, so something clunkier is needed. You can arrange for the background process to send a terminating signal to its parent upon exiting:
#! /bin/sh
"$@"; kill $$; &
while read line; do :; done
pkill -P $!
kill $!
wait
This will have to waste another process to wait for the "$@"
command, and use the -P
(parent pid) selector of pkill
since $!
no longer refer to the "$@"
command, but to its parent. The extra kill $!
is still needed in case the "$@"
happens to be a built-in. Notice that there's no job control in scripts; all processes (including those started with &
) run in the same process group.
You can use p/kill -KILL
everywhere if a TERM
signal isn't enough.
Another, even clunkier workaround that only works with newer (>= 4.0) versions of bash is to use the nonstandard -t
(timeout) option of read
and exploit the fact that read
will return 1 upon EOF
and a status > 128 upon timeout:
#! /bin/bash
"$@" &
while :; do
read -t 1 line
case $? in
0) ;;
1) kill $!; wait; exit;;
*) kill -0 $! || exit;;
esac
done 2>/dev/null
This somehow seems to work with mksh
, too.
This is helpful! Note that the different return values forread
on timeout vsEOF
match what I see inhelp read
in Bash 5.0.2, but in Bash 3.2 there is no such distinction.
– Nathan Long
Jan 30 at 15:32
add a comment |
If your shell is dash
/busybox
, ksh93
or zsh
, you could set a trap on SIGCHLD
:
#! /bin/sh
trap exit CHLD
"$@" &
while read line; do :; done
kill $!
wait
This will exit as soon as the "$@" &
process has exited or the read
has got an EOF
.
But bash
has a nasty read
built-in, which is restarted in place when interrupted by a signal, so something clunkier is needed. You can arrange for the background process to send a terminating signal to its parent upon exiting:
#! /bin/sh
"$@"; kill $$; &
while read line; do :; done
pkill -P $!
kill $!
wait
This will have to waste another process to wait for the "$@"
command, and use the -P
(parent pid) selector of pkill
since $!
no longer refer to the "$@"
command, but to its parent. The extra kill $!
is still needed in case the "$@"
happens to be a built-in. Notice that there's no job control in scripts; all processes (including those started with &
) run in the same process group.
You can use p/kill -KILL
everywhere if a TERM
signal isn't enough.
Another, even clunkier workaround that only works with newer (>= 4.0) versions of bash is to use the nonstandard -t
(timeout) option of read
and exploit the fact that read
will return 1 upon EOF
and a status > 128 upon timeout:
#! /bin/bash
"$@" &
while :; do
read -t 1 line
case $? in
0) ;;
1) kill $!; wait; exit;;
*) kill -0 $! || exit;;
esac
done 2>/dev/null
This somehow seems to work with mksh
, too.
This is helpful! Note that the different return values forread
on timeout vsEOF
match what I see inhelp read
in Bash 5.0.2, but in Bash 3.2 there is no such distinction.
– Nathan Long
Jan 30 at 15:32
add a comment |
If your shell is dash
/busybox
, ksh93
or zsh
, you could set a trap on SIGCHLD
:
#! /bin/sh
trap exit CHLD
"$@" &
while read line; do :; done
kill $!
wait
This will exit as soon as the "$@" &
process has exited or the read
has got an EOF
.
But bash
has a nasty read
built-in, which is restarted in place when interrupted by a signal, so something clunkier is needed. You can arrange for the background process to send a terminating signal to its parent upon exiting:
#! /bin/sh
"$@"; kill $$; &
while read line; do :; done
pkill -P $!
kill $!
wait
This will have to waste another process to wait for the "$@"
command, and use the -P
(parent pid) selector of pkill
since $!
no longer refer to the "$@"
command, but to its parent. The extra kill $!
is still needed in case the "$@"
happens to be a built-in. Notice that there's no job control in scripts; all processes (including those started with &
) run in the same process group.
You can use p/kill -KILL
everywhere if a TERM
signal isn't enough.
Another, even clunkier workaround that only works with newer (>= 4.0) versions of bash is to use the nonstandard -t
(timeout) option of read
and exploit the fact that read
will return 1 upon EOF
and a status > 128 upon timeout:
#! /bin/bash
"$@" &
while :; do
read -t 1 line
case $? in
0) ;;
1) kill $!; wait; exit;;
*) kill -0 $! || exit;;
esac
done 2>/dev/null
This somehow seems to work with mksh
, too.
If your shell is dash
/busybox
, ksh93
or zsh
, you could set a trap on SIGCHLD
:
#! /bin/sh
trap exit CHLD
"$@" &
while read line; do :; done
kill $!
wait
This will exit as soon as the "$@" &
process has exited or the read
has got an EOF
.
But bash
has a nasty read
built-in, which is restarted in place when interrupted by a signal, so something clunkier is needed. You can arrange for the background process to send a terminating signal to its parent upon exiting:
#! /bin/sh
"$@"; kill $$; &
while read line; do :; done
pkill -P $!
kill $!
wait
This will have to waste another process to wait for the "$@"
command, and use the -P
(parent pid) selector of pkill
since $!
no longer refer to the "$@"
command, but to its parent. The extra kill $!
is still needed in case the "$@"
happens to be a built-in. Notice that there's no job control in scripts; all processes (including those started with &
) run in the same process group.
You can use p/kill -KILL
everywhere if a TERM
signal isn't enough.
Another, even clunkier workaround that only works with newer (>= 4.0) versions of bash is to use the nonstandard -t
(timeout) option of read
and exploit the fact that read
will return 1 upon EOF
and a status > 128 upon timeout:
#! /bin/bash
"$@" &
while :; do
read -t 1 line
case $? in
0) ;;
1) kill $!; wait; exit;;
*) kill -0 $! || exit;;
esac
done 2>/dev/null
This somehow seems to work with mksh
, too.
edited Jan 30 at 19:22
answered Jan 30 at 5:16
mosvymosvy
7,6421530
7,6421530
This is helpful! Note that the different return values forread
on timeout vsEOF
match what I see inhelp read
in Bash 5.0.2, but in Bash 3.2 there is no such distinction.
– Nathan Long
Jan 30 at 15:32
add a comment |
This is helpful! Note that the different return values forread
on timeout vsEOF
match what I see inhelp read
in Bash 5.0.2, but in Bash 3.2 there is no such distinction.
– Nathan Long
Jan 30 at 15:32
This is helpful! Note that the different return values for
read
on timeout vs EOF
match what I see in help read
in Bash 5.0.2, but in Bash 3.2 there is no such distinction.– Nathan Long
Jan 30 at 15:32
This is helpful! Note that the different return values for
read
on timeout vs EOF
match what I see in help read
in Bash 5.0.2, but in Bash 3.2 there is no such distinction.– Nathan Long
Jan 30 at 15:32
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%2f497567%2fhow-to-periodically-check-if-stdin-is-open%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