Tom Gundersen, 2011-06-26 17:00:
On Sun, Jun 26, 2011 at 4:06 PM, Dave Reisner<[email protected]>  wrote:
On Sun, Jun 26, 2011 at 03:12:24PM +0200, Kurt J. Bosch wrote:
Tom Gundersen, 2011-06-26 13:51:
On Sun, Jun 26, 2011 at 1:03 PM, Kurt J. Bosch
<[email protected]>    wrote:
The following test case (run in a terminal)

#!/bin/bash

# custom override example
stat_busy() {
        if (( PUSH_MSG )); then
                # This triggers the error in "$@" below
                # actual code was:
                # echo set message "$1">    "$spl_fifo"&
                :&
        fi
        echo "$1" BUSY
}

status() {
        stat_busy "$1"
        shift
        "$@"
        local retval=$?
        (( retval == 0 ))&&    echo DONE || echo FAIL "($retval)"
}

PUSH_MSG=0 status "test #0" cat<(echo foo)
PUSH_MSG=1 status "test #1" cat<(echo foo)

[...]

CCing Tom Gundersen.

Thanks.

I have not figured it out, but here is a more minimal test:


#!/bin/bash


test_one() {
        :&
        "$@"
}

test_two() {
        :
        "$@"
}

# working
test_one eval 'cat<(echo foo)'
test_two cat<(echo foo)

#not working
test_one cat<(echo foo)

Confirmed.

--
Kurt

Now I see it (at least in Tom's example). It's expected behavior. You're
only allowed to read the file descriptor created by a PE once. However,
because file descriptors are inherited by subshells, when the subshell
ends, the file descriptor is closed and it goes away. Look at what
happens when you modify the script slightly:

-------------------

#!/bin/bash

test_one() {
  ls /dev/fd/
  :&
  ls /dev/fd/
  "$@"
}

test_one cat<(echo foo)

-------------------

And then run it with debug output....

+foo[11]: test_one cat /dev/fd/63
+foo[4]: ls /dev/fd/
++foo[11]: echo foo
0  1  2  3  63
+foo[6]: ls /dev/fd/
+foo[5]: :
0  1  2  3
+foo[7]: cat /dev/fd/63
cat: /dev/fd/63: No such file or directory

The subshell inherits the descriptor and closes it on exit, destroying
it for the parent. The eval "works" because the FD for the process
substitution isn't created until _after_ the subshell.

Can we _not_ do this? Our old solution didn't require voodoo like this,
and it worked just fine (albeit a few more SLOC). Not everything needs
to be a one line operation. Perhaps we could just write a simple
function to take care of all these 1 line files that we write to:

write_oneline_file() {
  local file=$1 line=$2 mode=$3

  printf '%s\n' "$line" >"$file"
  [[ $mode ]] &&  chmod "$mode" "$file"
}

Which satisfies both parties, as it appears to be a one liner in
execution, but it's actually sane on the back end.

Thanks for your explanation Dave. I like your solution, should make
things more readable.

-t

[sorry for duplicate, forgot CC]

I would like to go a bit further with this:
a) Drop the 'oneline' and the '\n' to be able to use it for any number of lines including zero.
b) Allow more options like owner, group, create parent directory.

Maybe like so:

install_file() {
  local file=$1 content=$2 # remaining args go to install directly
  shift 2
  install -T "$@" <(printf '%s' "$content") "$file"
}

Then these candidates:

 --- rc.sysinit ---
221: install -Tm 0664 -o root -g utmp <(:) /var/run/utmp
264: install -Tm 0600 <( dmesg ) /var/log/dmesg.log
266: install -Tm 0644 <( dmesg ) /var/log/dmesg.log
 --- rc.shutdown ---
24:  install -TDm 0600 <(:) $RANDOM_SEED

could be turned into:

 --- rc.sysinit ---
221: install_file /var/run/utmp "" -m 0664 -o root -g utmp
264: install_file /var/log/dmesg.log "$( dmesg )" -m 0600
266: install_file /var/log/dmesg.log "$( dmesg )" -m 0644
 --- rc.shutdown ---
24:  install_file $RANDOM_SEED "" -m 0600 -D

There is only one small drawback - we would need to add the trailing newline explicitly if wanted:

 --- rc.sysinit ---
232: install_file /etc/profile.d/locale.sh "export LANG=$LOCALE"$'\n' -m 0755

--
Kurt

Reply via email to