user4833046
user4833046

Reputation:

bash file descriptors - script doesnt work as expected

So in my script I call other script that needs 2 lines as init arguments.

The problem is that in the following snippet, the "script.sh" only takes first line (arg1). It doesn't seem to do anything useful with second line (arg2)

fun () {
    arg1="init argument one"
    arg2="init argument two"

    local PIPE=$(mktemp -u)
    mkfifo $PIPE
    eval "exec 3<>${PIPE}"
    rm $PIPE

    ./script.sh <&3 &
    echo "$arg1">&3
    echo "$arg2">&3
}

fun

Also, script behaves the same when I delete last echo

fun () {
    arg1="init argument one"
    arg2="init argument two"

    local PIPE=$(mktemp -u)
    mkfifo $PIPE
    eval "exec 3<>${PIPE}"
    rm $PIPE

    ./script.sh <&3 &
    echo "$arg1">&3
}

fun

Upvotes: 0

Views: 60

Answers (1)

Charles Duffy
Charles Duffy

Reputation: 295403

A FIFO has two sides, and each file descriptor is attached to only one side. That's true even when opened with O_RDWR, as you're doing with the <> operator; you can't actually both read and write from that single FD; it's simply a way to get a write handle without blocking for a reader to attach.

Thus, you must start a separate FD for your reader for the pipeline to work properly. Observe the following script's behavior, when run with at least two arguments:

#!/bin/bash

# mktemp -u is insecure; better to use mktemp -d and create fifo w/in
# see the EXIT trap for automatic tempfile cleanup
trap 'rm -rf "$tempdir"' EXIT
tempdir=$(mktemp -d pipeline.XXXXXX)
mkfifo "$tempdir/pipe"

exec 3<>"$tempdir/pipe"
bash -c 'read -r a1; read -r a2; printf "Read: %q\n" "$a1" "$a2"' \
  <"$tempdir/pipe" 3>&- &
printf '%s\n' "$@" >&3
wait

Upvotes: 2

Related Questions