How to create a bidirectional pipe in bash?
Clash Royale CLAN TAG#URR8PPP
I have a program which reads from and writes to file descriptor 3
. I want to let it write to fd 3
, and be able to write to the other end of the pipe interactively which the program should read over the same fd. I can create a pipe with mkfifo
(mkfifo /tmp/my_pipe
) and remap one end of it to fd 3
(./prog &3>/tmp/my_pipe
). I keep the pipe open using cat /tmp/my_pipe
. However, when the process tries to read from fd 3
, it receives a SIGTTIN
. Is it possible to launch the program as I intend from bash?
bash pipe mkfifo
add a comment |
I have a program which reads from and writes to file descriptor 3
. I want to let it write to fd 3
, and be able to write to the other end of the pipe interactively which the program should read over the same fd. I can create a pipe with mkfifo
(mkfifo /tmp/my_pipe
) and remap one end of it to fd 3
(./prog &3>/tmp/my_pipe
). I keep the pipe open using cat /tmp/my_pipe
. However, when the process tries to read from fd 3
, it receives a SIGTTIN
. Is it possible to launch the program as I intend from bash?
bash pipe mkfifo
1
unix.stackexchange.com/questions/53641/…
– ozzy
Jan 8 at 22:03
add a comment |
I have a program which reads from and writes to file descriptor 3
. I want to let it write to fd 3
, and be able to write to the other end of the pipe interactively which the program should read over the same fd. I can create a pipe with mkfifo
(mkfifo /tmp/my_pipe
) and remap one end of it to fd 3
(./prog &3>/tmp/my_pipe
). I keep the pipe open using cat /tmp/my_pipe
. However, when the process tries to read from fd 3
, it receives a SIGTTIN
. Is it possible to launch the program as I intend from bash?
bash pipe mkfifo
I have a program which reads from and writes to file descriptor 3
. I want to let it write to fd 3
, and be able to write to the other end of the pipe interactively which the program should read over the same fd. I can create a pipe with mkfifo
(mkfifo /tmp/my_pipe
) and remap one end of it to fd 3
(./prog &3>/tmp/my_pipe
). I keep the pipe open using cat /tmp/my_pipe
. However, when the process tries to read from fd 3
, it receives a SIGTTIN
. Is it possible to launch the program as I intend from bash?
bash pipe mkfifo
bash pipe mkfifo
asked Jan 8 at 21:12
Holmes.SherlockHolmes.Sherlock
224110
224110
1
unix.stackexchange.com/questions/53641/…
– ozzy
Jan 8 at 22:03
add a comment |
1
unix.stackexchange.com/questions/53641/…
– ozzy
Jan 8 at 22:03
1
1
unix.stackexchange.com/questions/53641/…
– ozzy
Jan 8 at 22:03
unix.stackexchange.com/questions/53641/…
– ozzy
Jan 8 at 22:03
add a comment |
1 Answer
1
active
oldest
votes
On (at least) Linux-based systems a FIFO or Named Pipe is unidirectional. In your situation you want to have a program reading and writing to the same FIFO. This gets even more tricky because you may well up with a deadlock if you exceed the pipe's internal buffer.
Two general points.
You cannot usefully have two readers; if you do, you'll find that your reads will interleave nondeterministically and your data will be shared between the two readers. You will not get the same data duplicated to both readers.
You can have two (or more) writers, but once again your output data will be interleaved in the order that it is received by the pipe. Unless your writers are carefully synchronised, data such as
First writer
andSecond writer
could end up being received as the garbledFirSecond wrstwrititerer
.
Using the program at the bottom of this answer, consider running the following two scenarios from different terminal sessions. Then try your own variations.
First terminal Second terminal Third terminal
-------------------- -------------------- --------------------
./fifo.sh read ./fifo.sh read ./fifo.sh write /etc/hosts
First terminal Second terminal Third terminal
-------------------- -------------------- --------------------
./fifo.sh write /etc/passwd ps -ef | ./fifo.sh write ./fifo.sh read
First terminal Second terminal Third terminal
-------------------- -------------------- --------------------
./fifo.sh both /etc/passwd
Script for fifo.sh
as follows
#!/bin/bash
#
pipe=/tmp/mypipe
########################################################################
# Reader
#
doRead()
echo "Reading from pipe $pipe" >&2
nl <"$pipe"
########################################################################
# Writer. We pause after every line (for effect)
#
doWrite()
while IFS= read -r line; do printf "%sn" "$line"; sleep 1; done >>"$pipe"
########################################################################
# Reader-Writer. We pause after every line (for effect)
#
doBoth()
[[ $# -eq 0 ]] && set -- -
echo "Reading and writing to pipe $pipe" >&2
exec 3<>"$pipe"
nl <&3 & readPID=$!
cat "$@"
########################################################################
#
action="$1"
shift
if [[ ! -p "$pipe" ]]
then
echo "Creating pipe $pipe" >&2
mkfifo "$pipe"
fi
case "$action" in
read*) doRead "$@" ;;
write*) doWrite "$@" ;;
both) doBoth "$@" ;;
esac
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%2f493331%2fhow-to-create-a-bidirectional-pipe-in-bash%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
On (at least) Linux-based systems a FIFO or Named Pipe is unidirectional. In your situation you want to have a program reading and writing to the same FIFO. This gets even more tricky because you may well up with a deadlock if you exceed the pipe's internal buffer.
Two general points.
You cannot usefully have two readers; if you do, you'll find that your reads will interleave nondeterministically and your data will be shared between the two readers. You will not get the same data duplicated to both readers.
You can have two (or more) writers, but once again your output data will be interleaved in the order that it is received by the pipe. Unless your writers are carefully synchronised, data such as
First writer
andSecond writer
could end up being received as the garbledFirSecond wrstwrititerer
.
Using the program at the bottom of this answer, consider running the following two scenarios from different terminal sessions. Then try your own variations.
First terminal Second terminal Third terminal
-------------------- -------------------- --------------------
./fifo.sh read ./fifo.sh read ./fifo.sh write /etc/hosts
First terminal Second terminal Third terminal
-------------------- -------------------- --------------------
./fifo.sh write /etc/passwd ps -ef | ./fifo.sh write ./fifo.sh read
First terminal Second terminal Third terminal
-------------------- -------------------- --------------------
./fifo.sh both /etc/passwd
Script for fifo.sh
as follows
#!/bin/bash
#
pipe=/tmp/mypipe
########################################################################
# Reader
#
doRead()
echo "Reading from pipe $pipe" >&2
nl <"$pipe"
########################################################################
# Writer. We pause after every line (for effect)
#
doWrite()
while IFS= read -r line; do printf "%sn" "$line"; sleep 1; done >>"$pipe"
########################################################################
# Reader-Writer. We pause after every line (for effect)
#
doBoth()
[[ $# -eq 0 ]] && set -- -
echo "Reading and writing to pipe $pipe" >&2
exec 3<>"$pipe"
nl <&3 & readPID=$!
cat "$@"
########################################################################
#
action="$1"
shift
if [[ ! -p "$pipe" ]]
then
echo "Creating pipe $pipe" >&2
mkfifo "$pipe"
fi
case "$action" in
read*) doRead "$@" ;;
write*) doWrite "$@" ;;
both) doBoth "$@" ;;
esac
add a comment |
On (at least) Linux-based systems a FIFO or Named Pipe is unidirectional. In your situation you want to have a program reading and writing to the same FIFO. This gets even more tricky because you may well up with a deadlock if you exceed the pipe's internal buffer.
Two general points.
You cannot usefully have two readers; if you do, you'll find that your reads will interleave nondeterministically and your data will be shared between the two readers. You will not get the same data duplicated to both readers.
You can have two (or more) writers, but once again your output data will be interleaved in the order that it is received by the pipe. Unless your writers are carefully synchronised, data such as
First writer
andSecond writer
could end up being received as the garbledFirSecond wrstwrititerer
.
Using the program at the bottom of this answer, consider running the following two scenarios from different terminal sessions. Then try your own variations.
First terminal Second terminal Third terminal
-------------------- -------------------- --------------------
./fifo.sh read ./fifo.sh read ./fifo.sh write /etc/hosts
First terminal Second terminal Third terminal
-------------------- -------------------- --------------------
./fifo.sh write /etc/passwd ps -ef | ./fifo.sh write ./fifo.sh read
First terminal Second terminal Third terminal
-------------------- -------------------- --------------------
./fifo.sh both /etc/passwd
Script for fifo.sh
as follows
#!/bin/bash
#
pipe=/tmp/mypipe
########################################################################
# Reader
#
doRead()
echo "Reading from pipe $pipe" >&2
nl <"$pipe"
########################################################################
# Writer. We pause after every line (for effect)
#
doWrite()
while IFS= read -r line; do printf "%sn" "$line"; sleep 1; done >>"$pipe"
########################################################################
# Reader-Writer. We pause after every line (for effect)
#
doBoth()
[[ $# -eq 0 ]] && set -- -
echo "Reading and writing to pipe $pipe" >&2
exec 3<>"$pipe"
nl <&3 & readPID=$!
cat "$@"
########################################################################
#
action="$1"
shift
if [[ ! -p "$pipe" ]]
then
echo "Creating pipe $pipe" >&2
mkfifo "$pipe"
fi
case "$action" in
read*) doRead "$@" ;;
write*) doWrite "$@" ;;
both) doBoth "$@" ;;
esac
add a comment |
On (at least) Linux-based systems a FIFO or Named Pipe is unidirectional. In your situation you want to have a program reading and writing to the same FIFO. This gets even more tricky because you may well up with a deadlock if you exceed the pipe's internal buffer.
Two general points.
You cannot usefully have two readers; if you do, you'll find that your reads will interleave nondeterministically and your data will be shared between the two readers. You will not get the same data duplicated to both readers.
You can have two (or more) writers, but once again your output data will be interleaved in the order that it is received by the pipe. Unless your writers are carefully synchronised, data such as
First writer
andSecond writer
could end up being received as the garbledFirSecond wrstwrititerer
.
Using the program at the bottom of this answer, consider running the following two scenarios from different terminal sessions. Then try your own variations.
First terminal Second terminal Third terminal
-------------------- -------------------- --------------------
./fifo.sh read ./fifo.sh read ./fifo.sh write /etc/hosts
First terminal Second terminal Third terminal
-------------------- -------------------- --------------------
./fifo.sh write /etc/passwd ps -ef | ./fifo.sh write ./fifo.sh read
First terminal Second terminal Third terminal
-------------------- -------------------- --------------------
./fifo.sh both /etc/passwd
Script for fifo.sh
as follows
#!/bin/bash
#
pipe=/tmp/mypipe
########################################################################
# Reader
#
doRead()
echo "Reading from pipe $pipe" >&2
nl <"$pipe"
########################################################################
# Writer. We pause after every line (for effect)
#
doWrite()
while IFS= read -r line; do printf "%sn" "$line"; sleep 1; done >>"$pipe"
########################################################################
# Reader-Writer. We pause after every line (for effect)
#
doBoth()
[[ $# -eq 0 ]] && set -- -
echo "Reading and writing to pipe $pipe" >&2
exec 3<>"$pipe"
nl <&3 & readPID=$!
cat "$@"
########################################################################
#
action="$1"
shift
if [[ ! -p "$pipe" ]]
then
echo "Creating pipe $pipe" >&2
mkfifo "$pipe"
fi
case "$action" in
read*) doRead "$@" ;;
write*) doWrite "$@" ;;
both) doBoth "$@" ;;
esac
On (at least) Linux-based systems a FIFO or Named Pipe is unidirectional. In your situation you want to have a program reading and writing to the same FIFO. This gets even more tricky because you may well up with a deadlock if you exceed the pipe's internal buffer.
Two general points.
You cannot usefully have two readers; if you do, you'll find that your reads will interleave nondeterministically and your data will be shared between the two readers. You will not get the same data duplicated to both readers.
You can have two (or more) writers, but once again your output data will be interleaved in the order that it is received by the pipe. Unless your writers are carefully synchronised, data such as
First writer
andSecond writer
could end up being received as the garbledFirSecond wrstwrititerer
.
Using the program at the bottom of this answer, consider running the following two scenarios from different terminal sessions. Then try your own variations.
First terminal Second terminal Third terminal
-------------------- -------------------- --------------------
./fifo.sh read ./fifo.sh read ./fifo.sh write /etc/hosts
First terminal Second terminal Third terminal
-------------------- -------------------- --------------------
./fifo.sh write /etc/passwd ps -ef | ./fifo.sh write ./fifo.sh read
First terminal Second terminal Third terminal
-------------------- -------------------- --------------------
./fifo.sh both /etc/passwd
Script for fifo.sh
as follows
#!/bin/bash
#
pipe=/tmp/mypipe
########################################################################
# Reader
#
doRead()
echo "Reading from pipe $pipe" >&2
nl <"$pipe"
########################################################################
# Writer. We pause after every line (for effect)
#
doWrite()
while IFS= read -r line; do printf "%sn" "$line"; sleep 1; done >>"$pipe"
########################################################################
# Reader-Writer. We pause after every line (for effect)
#
doBoth()
[[ $# -eq 0 ]] && set -- -
echo "Reading and writing to pipe $pipe" >&2
exec 3<>"$pipe"
nl <&3 & readPID=$!
cat "$@"
########################################################################
#
action="$1"
shift
if [[ ! -p "$pipe" ]]
then
echo "Creating pipe $pipe" >&2
mkfifo "$pipe"
fi
case "$action" in
read*) doRead "$@" ;;
write*) doWrite "$@" ;;
both) doBoth "$@" ;;
esac
edited Jan 8 at 22:15
answered Jan 8 at 22:02
roaimaroaima
43.6k554117
43.6k554117
add a comment |
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%2f493331%2fhow-to-create-a-bidirectional-pipe-in-bash%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
unix.stackexchange.com/questions/53641/…
– ozzy
Jan 8 at 22:03