| Summary: | Bizarre file descriptor race condition | ||
|---|---|---|---|
| Product: | Base System | Reporter: | Aragon Gouveia <aragon> |
| Component: | bin | Assignee: | Jilles Tjoelker <jilles> |
| Status: | Closed FIXED | ||
| Severity: | Affects Only Me | ||
| Priority: | Normal | ||
| Version: | 8.2-STABLE | ||
| Hardware: | Any | ||
| OS: | Any | ||
State Changed
From-To: open->closed
This is not a bug but a fairly common caveat with ssh(1).
The problem is that ssh(1) does not know if the other side wants
input and therefore it reads data and sends it to the other side.
Once data has been read from a pipe there is no way to put it back.
It would be possible with a regular file but determining the amount
to put back would be very complicated and unreliable.
If the other side is very fast, it might finish executing the
command before ssh(1) attempts its first read and the script
might work as intended.
You can solve the problem by redirecting ssh's input (either with
shell redirection or with the -n option) or by using a different
file descriptor for the list, like:
while read hostid hostname <&3; do
echo ${hostid}:${hostname}
ssh ${hostname} 'df -k'
done 3<${DFRTMP}/hosts
Responsible Changed From-To: freebsd-bugs->jilles Track. |
Please see the script pasted in the repeat field. When it is run, the while loop exits after the first iteration. However, if the ssh command is commented, the loop executes two iterations. Stranger still, on some of my FreeBSD systems the script works correctly _sometimes_, but mostly not. How-To-Repeat: #!/bin/sh DFRTMP=$(mktemp -d /tmp/dfr.XXXXXX) [ $? -eq 0 ] || exit 1 cat >${DFRTMP}/hosts <<"_EOF" 1 saturn.geek.sh 2 null _EOF while read hostid hostname; do echo ${hostid}:${hostname} ssh ${hostname} 'df -k' done <${DFRTMP}/hosts rm -rf ${DFRTMP}