Run command in background with foreground terminal access2019 Community Moderator Electionbash: Run command in background and capture pidShell script wait for background commandHow shell get control of the terminal after wait()?How to wait for all spawned and backgrounded processes to finish in bash scriptBetter way to go to background in a running commandWhat is the main difference between foreground and background process?Background, zombie, daemon and without ctty - are these concepts connected?Control characters in a terminal with an active foreground processSending a signal to a parent processKilling jobs started within functions
Plot of a tornado-shaped surface
Strong empirical falsification of quantum mechanics based on vacuum energy density
Does IPv6 have similar concept of network mask?
Why is this estimator biased?
Store Credit Card Information in Password Manager?
On a tidally locked planet, would time be quantized?
What does "Scientists rise up against statistical significance" mean? (Comment in Nature)
Did arcade monitors have same pixel aspect ratio as TV sets?
Is there a RAID 0 Equivalent for RAM?
Using substitution ciphers to generate new alphabets in a novel
The IT department bottlenecks progress. How should I handle this?
Creepy dinosaur pc game identification
What is going on with 'gets(stdin)' on the site coderbyte?
When were female captains banned from Starfleet?
Does malloc reserve more space while allocating memory?
Is this toilet slogan correct usage of the English language?
Does Doodling or Improvising on the Piano Have Any Benefits?
Can I say "fingers" when referring to toes?
What should you do when eye contact makes your subordinate uncomfortable?
How to cover method return statement in Apex Class?
Hero deduces identity of a killer
What is the highest possible scrabble score for placing a single tile
Is aluminum electrical wire used on aircraft?
Fear of getting stuck on one programming language / technology that is not used in my country
Run command in background with foreground terminal access
2019 Community Moderator Electionbash: Run command in background and capture pidShell script wait for background commandHow shell get control of the terminal after wait()?How to wait for all spawned and backgrounded processes to finish in bash scriptBetter way to go to background in a running commandWhat is the main difference between foreground and background process?Background, zombie, daemon and without ctty - are these concepts connected?Control characters in a terminal with an active foreground processSending a signal to a parent processKilling jobs started within functions
I am trying to create a function that can run an arbitrary command, interact with the child process (specifics omitted), and then wait for it to exit. If successful, typing run <command>
will appear to behave just like a bare <command>
.
If I weren't interacting with the child process I would simply write:
run()
"$@"
But because I need to interact with it while it runs, I have this more complicated setup with coproc
and wait
.
run()
exec in<&0 out>&1 err>&2
coproc "$@" 0<&$in 1>&$out 2>&$err; 2>/dev/null
exec in<&- out>&- err>&-
# while child running:
# status/signal/exchange data with child process
wait
(This is a simplification. While the coproc
and all the redirections aren't really doing anything useful here that "$@" &
couldn't do, I need them all in my real program.)
The "$@"
command could be anything. The function I have works with run ls
and run make
and the like, but it fails when I do run vim
. It fails, I presume, because Vim detects that it is a background process and doesn't have terminal access, so instead of popping up an edit window it suspends itself. I want to fix it so Vim behaves normally.
How can I make coproc "$@"
run in the "foreground" and the parent shell become the "background"? The "interact with child" part neither reads from nor writes to the terminal, so I don't need it to run in the foreground. I'm happy to hand over control of the tty to the coprocess.
It is important for what I'm doing that run()
be in the parent process and "$@"
be in its child. I can't swap those roles. But I can swap the foreground and background. (I just don't know how to.)
Note that I am not looking for a Vim-specific solution. And I would prefer to avoid pseudo-ttys. My ideal solution would work equally well when stdin and stdout are connected to a tty, to pipes, or are redirected from files:
run echo foo # should print "foo"
echo foo | run sed 's/foo/bar/' | cat # should print "bar"
run vim # should open vim normally
shell tty background-process job-control coprocesses
add a comment |
I am trying to create a function that can run an arbitrary command, interact with the child process (specifics omitted), and then wait for it to exit. If successful, typing run <command>
will appear to behave just like a bare <command>
.
If I weren't interacting with the child process I would simply write:
run()
"$@"
But because I need to interact with it while it runs, I have this more complicated setup with coproc
and wait
.
run()
exec in<&0 out>&1 err>&2
coproc "$@" 0<&$in 1>&$out 2>&$err; 2>/dev/null
exec in<&- out>&- err>&-
# while child running:
# status/signal/exchange data with child process
wait
(This is a simplification. While the coproc
and all the redirections aren't really doing anything useful here that "$@" &
couldn't do, I need them all in my real program.)
The "$@"
command could be anything. The function I have works with run ls
and run make
and the like, but it fails when I do run vim
. It fails, I presume, because Vim detects that it is a background process and doesn't have terminal access, so instead of popping up an edit window it suspends itself. I want to fix it so Vim behaves normally.
How can I make coproc "$@"
run in the "foreground" and the parent shell become the "background"? The "interact with child" part neither reads from nor writes to the terminal, so I don't need it to run in the foreground. I'm happy to hand over control of the tty to the coprocess.
It is important for what I'm doing that run()
be in the parent process and "$@"
be in its child. I can't swap those roles. But I can swap the foreground and background. (I just don't know how to.)
Note that I am not looking for a Vim-specific solution. And I would prefer to avoid pseudo-ttys. My ideal solution would work equally well when stdin and stdout are connected to a tty, to pipes, or are redirected from files:
run echo foo # should print "foo"
echo foo | run sed 's/foo/bar/' | cat # should print "bar"
run vim # should open vim normally
shell tty background-process job-control coprocesses
1
What does "interact with the child process" entail? The script interacting with it, programmatically? You interacting with it? Are you reinventingexpect
?
– JdeBP
yesterday
The script interacting with it, not the user. Maybe statusing it, sending it a signal, something like that. (In my full script I'm using thecoproc
FIFO as a side channel to send and receive data.)
– John Kugelman
yesterday
add a comment |
I am trying to create a function that can run an arbitrary command, interact with the child process (specifics omitted), and then wait for it to exit. If successful, typing run <command>
will appear to behave just like a bare <command>
.
If I weren't interacting with the child process I would simply write:
run()
"$@"
But because I need to interact with it while it runs, I have this more complicated setup with coproc
and wait
.
run()
exec in<&0 out>&1 err>&2
coproc "$@" 0<&$in 1>&$out 2>&$err; 2>/dev/null
exec in<&- out>&- err>&-
# while child running:
# status/signal/exchange data with child process
wait
(This is a simplification. While the coproc
and all the redirections aren't really doing anything useful here that "$@" &
couldn't do, I need them all in my real program.)
The "$@"
command could be anything. The function I have works with run ls
and run make
and the like, but it fails when I do run vim
. It fails, I presume, because Vim detects that it is a background process and doesn't have terminal access, so instead of popping up an edit window it suspends itself. I want to fix it so Vim behaves normally.
How can I make coproc "$@"
run in the "foreground" and the parent shell become the "background"? The "interact with child" part neither reads from nor writes to the terminal, so I don't need it to run in the foreground. I'm happy to hand over control of the tty to the coprocess.
It is important for what I'm doing that run()
be in the parent process and "$@"
be in its child. I can't swap those roles. But I can swap the foreground and background. (I just don't know how to.)
Note that I am not looking for a Vim-specific solution. And I would prefer to avoid pseudo-ttys. My ideal solution would work equally well when stdin and stdout are connected to a tty, to pipes, or are redirected from files:
run echo foo # should print "foo"
echo foo | run sed 's/foo/bar/' | cat # should print "bar"
run vim # should open vim normally
shell tty background-process job-control coprocesses
I am trying to create a function that can run an arbitrary command, interact with the child process (specifics omitted), and then wait for it to exit. If successful, typing run <command>
will appear to behave just like a bare <command>
.
If I weren't interacting with the child process I would simply write:
run()
"$@"
But because I need to interact with it while it runs, I have this more complicated setup with coproc
and wait
.
run()
exec in<&0 out>&1 err>&2
coproc "$@" 0<&$in 1>&$out 2>&$err; 2>/dev/null
exec in<&- out>&- err>&-
# while child running:
# status/signal/exchange data with child process
wait
(This is a simplification. While the coproc
and all the redirections aren't really doing anything useful here that "$@" &
couldn't do, I need them all in my real program.)
The "$@"
command could be anything. The function I have works with run ls
and run make
and the like, but it fails when I do run vim
. It fails, I presume, because Vim detects that it is a background process and doesn't have terminal access, so instead of popping up an edit window it suspends itself. I want to fix it so Vim behaves normally.
How can I make coproc "$@"
run in the "foreground" and the parent shell become the "background"? The "interact with child" part neither reads from nor writes to the terminal, so I don't need it to run in the foreground. I'm happy to hand over control of the tty to the coprocess.
It is important for what I'm doing that run()
be in the parent process and "$@"
be in its child. I can't swap those roles. But I can swap the foreground and background. (I just don't know how to.)
Note that I am not looking for a Vim-specific solution. And I would prefer to avoid pseudo-ttys. My ideal solution would work equally well when stdin and stdout are connected to a tty, to pipes, or are redirected from files:
run echo foo # should print "foo"
echo foo | run sed 's/foo/bar/' | cat # should print "bar"
run vim # should open vim normally
shell tty background-process job-control coprocesses
shell tty background-process job-control coprocesses
edited yesterday
John Kugelman
asked yesterday
John KugelmanJohn Kugelman
1,67911018
1,67911018
1
What does "interact with the child process" entail? The script interacting with it, programmatically? You interacting with it? Are you reinventingexpect
?
– JdeBP
yesterday
The script interacting with it, not the user. Maybe statusing it, sending it a signal, something like that. (In my full script I'm using thecoproc
FIFO as a side channel to send and receive data.)
– John Kugelman
yesterday
add a comment |
1
What does "interact with the child process" entail? The script interacting with it, programmatically? You interacting with it? Are you reinventingexpect
?
– JdeBP
yesterday
The script interacting with it, not the user. Maybe statusing it, sending it a signal, something like that. (In my full script I'm using thecoproc
FIFO as a side channel to send and receive data.)
– John Kugelman
yesterday
1
1
What does "interact with the child process" entail? The script interacting with it, programmatically? You interacting with it? Are you reinventing
expect
?– JdeBP
yesterday
What does "interact with the child process" entail? The script interacting with it, programmatically? You interacting with it? Are you reinventing
expect
?– JdeBP
yesterday
The script interacting with it, not the user. Maybe statusing it, sending it a signal, something like that. (In my full script I'm using the
coproc
FIFO as a side channel to send and receive data.)– John Kugelman
yesterday
The script interacting with it, not the user. Maybe statusing it, sending it a signal, something like that. (In my full script I'm using the
coproc
FIFO as a side channel to send and receive data.)– John Kugelman
yesterday
add a comment |
1 Answer
1
active
oldest
votes
I've added code so that:
interact()
pid=$1
! ps -p $pid && return
ls -ld /proc/$pid/fd/*
sleep 5; kill -1 $pid # TEST SIGNAL TO PARENT
run()
exec in<&0 out>&1 err>&2
coproc "$@" 0<&$in 1>&$out 2>&$err; 2>/dev/null
exec in<&- out>&- err>&-
interact $! <&- >/tmp/whatever.log 2>&1& 2>/dev/null
fg %1 >/dev/null 2>&1
wait 2>/dev/null
The fg %1
will run for all commands (change %1
as needed for concurrent jobs) and under normal circumstances one of two things will happen:
interact()
will return immediately since there is nothing to do and the fg
will do nothing.interact()
can interact (eg. send a HUP to the coprocess after 5 seconds) and the fg
will put the coprocess in the foreground using the same stdin/out/err with which it was originally run (you can check this with ls -l /proc/<pid>/df
).The redirections to /dev/null in the last three commands are cosmetic. They allow run <command>
to appear exactly the same as if you had run command
on its own.
I'd prefer it if Vim didn't suspend itself in the first place. This would be a complicated workaround to implement because I want the "interact with child" bits to run before I callwait
. The interaction I'm doing is in fact a loop that runs until the co-process finishes. Thewait
is merely a formality to get its exit code; it doesn't actually do any waiting.
– John Kugelman
yesterday
Thanks for the ideas. Unfortunately I can't backgroundinteract
or run it in a subshell. It has to run in the parent shell.
– John Kugelman
5 hours ago
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%2f507786%2frun-command-in-background-with-foreground-terminal-access%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
I've added code so that:
interact()
pid=$1
! ps -p $pid && return
ls -ld /proc/$pid/fd/*
sleep 5; kill -1 $pid # TEST SIGNAL TO PARENT
run()
exec in<&0 out>&1 err>&2
coproc "$@" 0<&$in 1>&$out 2>&$err; 2>/dev/null
exec in<&- out>&- err>&-
interact $! <&- >/tmp/whatever.log 2>&1& 2>/dev/null
fg %1 >/dev/null 2>&1
wait 2>/dev/null
The fg %1
will run for all commands (change %1
as needed for concurrent jobs) and under normal circumstances one of two things will happen:
interact()
will return immediately since there is nothing to do and the fg
will do nothing.interact()
can interact (eg. send a HUP to the coprocess after 5 seconds) and the fg
will put the coprocess in the foreground using the same stdin/out/err with which it was originally run (you can check this with ls -l /proc/<pid>/df
).The redirections to /dev/null in the last three commands are cosmetic. They allow run <command>
to appear exactly the same as if you had run command
on its own.
I'd prefer it if Vim didn't suspend itself in the first place. This would be a complicated workaround to implement because I want the "interact with child" bits to run before I callwait
. The interaction I'm doing is in fact a loop that runs until the co-process finishes. Thewait
is merely a formality to get its exit code; it doesn't actually do any waiting.
– John Kugelman
yesterday
Thanks for the ideas. Unfortunately I can't backgroundinteract
or run it in a subshell. It has to run in the parent shell.
– John Kugelman
5 hours ago
add a comment |
I've added code so that:
interact()
pid=$1
! ps -p $pid && return
ls -ld /proc/$pid/fd/*
sleep 5; kill -1 $pid # TEST SIGNAL TO PARENT
run()
exec in<&0 out>&1 err>&2
coproc "$@" 0<&$in 1>&$out 2>&$err; 2>/dev/null
exec in<&- out>&- err>&-
interact $! <&- >/tmp/whatever.log 2>&1& 2>/dev/null
fg %1 >/dev/null 2>&1
wait 2>/dev/null
The fg %1
will run for all commands (change %1
as needed for concurrent jobs) and under normal circumstances one of two things will happen:
interact()
will return immediately since there is nothing to do and the fg
will do nothing.interact()
can interact (eg. send a HUP to the coprocess after 5 seconds) and the fg
will put the coprocess in the foreground using the same stdin/out/err with which it was originally run (you can check this with ls -l /proc/<pid>/df
).The redirections to /dev/null in the last three commands are cosmetic. They allow run <command>
to appear exactly the same as if you had run command
on its own.
I'd prefer it if Vim didn't suspend itself in the first place. This would be a complicated workaround to implement because I want the "interact with child" bits to run before I callwait
. The interaction I'm doing is in fact a loop that runs until the co-process finishes. Thewait
is merely a formality to get its exit code; it doesn't actually do any waiting.
– John Kugelman
yesterday
Thanks for the ideas. Unfortunately I can't backgroundinteract
or run it in a subshell. It has to run in the parent shell.
– John Kugelman
5 hours ago
add a comment |
I've added code so that:
interact()
pid=$1
! ps -p $pid && return
ls -ld /proc/$pid/fd/*
sleep 5; kill -1 $pid # TEST SIGNAL TO PARENT
run()
exec in<&0 out>&1 err>&2
coproc "$@" 0<&$in 1>&$out 2>&$err; 2>/dev/null
exec in<&- out>&- err>&-
interact $! <&- >/tmp/whatever.log 2>&1& 2>/dev/null
fg %1 >/dev/null 2>&1
wait 2>/dev/null
The fg %1
will run for all commands (change %1
as needed for concurrent jobs) and under normal circumstances one of two things will happen:
interact()
will return immediately since there is nothing to do and the fg
will do nothing.interact()
can interact (eg. send a HUP to the coprocess after 5 seconds) and the fg
will put the coprocess in the foreground using the same stdin/out/err with which it was originally run (you can check this with ls -l /proc/<pid>/df
).The redirections to /dev/null in the last three commands are cosmetic. They allow run <command>
to appear exactly the same as if you had run command
on its own.
I've added code so that:
interact()
pid=$1
! ps -p $pid && return
ls -ld /proc/$pid/fd/*
sleep 5; kill -1 $pid # TEST SIGNAL TO PARENT
run()
exec in<&0 out>&1 err>&2
coproc "$@" 0<&$in 1>&$out 2>&$err; 2>/dev/null
exec in<&- out>&- err>&-
interact $! <&- >/tmp/whatever.log 2>&1& 2>/dev/null
fg %1 >/dev/null 2>&1
wait 2>/dev/null
The fg %1
will run for all commands (change %1
as needed for concurrent jobs) and under normal circumstances one of two things will happen:
interact()
will return immediately since there is nothing to do and the fg
will do nothing.interact()
can interact (eg. send a HUP to the coprocess after 5 seconds) and the fg
will put the coprocess in the foreground using the same stdin/out/err with which it was originally run (you can check this with ls -l /proc/<pid>/df
).The redirections to /dev/null in the last three commands are cosmetic. They allow run <command>
to appear exactly the same as if you had run command
on its own.
edited 6 hours ago
answered yesterday
Colin PearseColin Pearse
263
263
I'd prefer it if Vim didn't suspend itself in the first place. This would be a complicated workaround to implement because I want the "interact with child" bits to run before I callwait
. The interaction I'm doing is in fact a loop that runs until the co-process finishes. Thewait
is merely a formality to get its exit code; it doesn't actually do any waiting.
– John Kugelman
yesterday
Thanks for the ideas. Unfortunately I can't backgroundinteract
or run it in a subshell. It has to run in the parent shell.
– John Kugelman
5 hours ago
add a comment |
I'd prefer it if Vim didn't suspend itself in the first place. This would be a complicated workaround to implement because I want the "interact with child" bits to run before I callwait
. The interaction I'm doing is in fact a loop that runs until the co-process finishes. Thewait
is merely a formality to get its exit code; it doesn't actually do any waiting.
– John Kugelman
yesterday
Thanks for the ideas. Unfortunately I can't backgroundinteract
or run it in a subshell. It has to run in the parent shell.
– John Kugelman
5 hours ago
I'd prefer it if Vim didn't suspend itself in the first place. This would be a complicated workaround to implement because I want the "interact with child" bits to run before I call
wait
. The interaction I'm doing is in fact a loop that runs until the co-process finishes. The wait
is merely a formality to get its exit code; it doesn't actually do any waiting.– John Kugelman
yesterday
I'd prefer it if Vim didn't suspend itself in the first place. This would be a complicated workaround to implement because I want the "interact with child" bits to run before I call
wait
. The interaction I'm doing is in fact a loop that runs until the co-process finishes. The wait
is merely a formality to get its exit code; it doesn't actually do any waiting.– John Kugelman
yesterday
Thanks for the ideas. Unfortunately I can't background
interact
or run it in a subshell. It has to run in the parent shell.– John Kugelman
5 hours ago
Thanks for the ideas. Unfortunately I can't background
interact
or run it in a subshell. It has to run in the parent shell.– John Kugelman
5 hours ago
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%2f507786%2frun-command-in-background-with-foreground-terminal-access%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
1
What does "interact with the child process" entail? The script interacting with it, programmatically? You interacting with it? Are you reinventing
expect
?– JdeBP
yesterday
The script interacting with it, not the user. Maybe statusing it, sending it a signal, something like that. (In my full script I'm using the
coproc
FIFO as a side channel to send and receive data.)– John Kugelman
yesterday