I have a similar problem to report as Fiedler Roman regarding read and also another problem regarding while. Maybe the while case is intended behavior though. =)
See comments in the script below. bash --version GNU bash, version 4.2.39(1)-release (x86_64-redhat-linux-gnu) Example script starts here. #!/bin/bash -x fifo_dir=`mktemp -d` xl_console_input="$fifo_dir/fifo_in" xl_console_output="$fifo_dir/fifo_out" function domain_running { local domain="$1" xl list "$domain" >/dev/null 2>&1 } # I've also tried variants like: # IFS= read -N 16384 -r -t 2 -d '' data # which neither put anything into $data. function poke_console { local data local ret # Pole the console, see what happens. echo # Now read all data available from the console. while : do # Now, read from the console, with \n as delimiter. read -t 2 data ret=$? # Problem is here, $data is empty when read has timed out, i.e, not # read a complete line. I expect data to contain the line read so # far. echo "$data" >&2 # If we didn't time out, there's more data available # that we want to flush. [[ $ret -gt 128 ]] || continue # Ok, so we've timed out, I already know that $data doesn't contain the # reminder of the line, let's try getting it by looking for another delimiter. # : is the delimiter we expect if we're seeing the login prompt which should # be the usual case. read -d':' -t 1 data # Data is still empty here ... if [[ -n "$data" ]] then [[ "$data" =~ "login" ]] && return 0 fi # And this delimiter is if someone has left the console logged in. read -d'#' -t 1 data # ... and here too. if [[ -n "$data" ]] then [[ "$data" =~ 'root@' ]] && return 1 fi # And data is empty on the next iteration of the loop too. done < "$xl_console_output" # Console is in an unknown state. return 100 } function parse_until { # Cut away for brevity. } function remove_pipe_dir { rm -r "$fifo_dir" } trap remove_pipe_dir TERM # It the below also a bug? # while can't handle nulls, this doesn't work: # while read -d \x00 cfg # while this does work: # read -d \x00 test < <(find . -name some_file -print0) ; echo $test while read cfg do name=`sed -rn 's/name.*=[[:space:]]*"(.*)"/\1/p' "$cfg"` domain_running "$name" || continue mkfifo "$xl_console_input" mkfifo "$xl_console_output" xl console "${name}" < "$xl_console_input" > "$xl_console_output" & ( poke_console case $? in 0) echo root parse_until 'assword' echo password ;; 1) echo "\`date\` ': BAD YOU! CONSOLE WAS NOT LOGGED OUT!' >> /root/I_will_never_again_leave_my_computer_unlocked" ;; 100) echo "Can't find login prompt nor root prompt." >&2 esac parse_until 'root@' '#' || exit $? # Exit if we can't login. echo date -u -s \""`date -u "+%Y-%m-%d %H:%M:%S.%N UTC" -d "now"`"\" parse_until 'root@' '#' echo exit ) > "$xl_console_input" rm "$xl_console_input" "$xl_console_output" # This doesn't work, combined with the read -r \x00 above. #done < <(find /guests/vmname -name "xl.config" -print0) done < <(find /guests/vmname -name "xl.config") End of script here. Sample output, supposed error marked in the output below: [root@machine ~]# sync_time ++ mktemp -d + fifo_dir=/tmp/tmp.SbGOeR3Nk1 + xl_console_input=/tmp/tmp.SbGOeR3Nk1/fifo_in + xl_console_output=/tmp/tmp.SbGOeR3Nk1/fifo_out + trap remove_fifo_dir TERM INT + read cfg ++ find /guests/vmname -name xl.config ++ sed -rn 's/name.*=[[:space:]]*"(.*)"/\1/p' /guests/vmname/xl.config + name=vmname + domain_running vmname + local domain=vmname + xl list vmname + mkfifo /tmp/tmp.SbGOeR3Nk1/fifo_in + mkfifo /tmp/tmp.SbGOeR3Nk1/fifo_out + xl console vmname + poke_console + local data + local ret + echo + : + read -t 2 data + ret=0 + echo $'\r' + [[ 0 -gt 128 ]] + continue + : + read -t 2 data + ret=0 + echo $'\r\r' + [[ 0 -gt 128 ]] + continue + : + read -t 2 data + ret=0 ' echo 'Fedora release 17 (Beefy Miracle) Fedora release 17 (Beefy Miracle) + [[ 0 -gt 128 ]] + continue + : + read -t 2 data + ret=0 ' echo 'Kernel 3.6.6-1.fc17.x86_64 on an x86_64 (hvc0) Kernel 3.6.6-1.fc17.x86_64 on an x86_64 (hvc0) + [[ 0 -gt 128 ]] + continue + : + read -t 2 data + ret=0 + echo $'\r' + [[ 0 -gt 128 ]] + continue + : + read -t 2 data + ret=142 # The line below is the line that I consider to be an error, it's empty and should contain # "vmname login: " + echo '' + [[ 142 -gt 128 ]] + echo + read -N 4096 -r -d : -t 1 data + [[ -n '' ]] + echo + read -n 4096 -r -d '#' -t 1 data + [[ -n '' ]] + : + read -t 2 data + ret=142 + echo '' + [[ 142 -gt 128 ]] + echo + read -N 4096 -r -d : -t 1 data ^C++ remove_fifo_dir ++ rm -r /tmp/tmp.SbGOeR3Nk1 ++ exit [user@machine user]$ So, did I do anything wrong or is this a bug with read? =) I could not find anything in the man page for bash regarding while exiting upon receiving \0. Is there any specific reason for it to exit on \0 instead of exiting at EOF? Regards / Linus