ssh在bash中中断while循环
我使用此bash代码将文件上载到远程服务器,对于普通文件,这可以正常工作:ssh在bash中中断while循环,bash,ssh,Bash,Ssh,我使用此bash代码将文件上载到远程服务器,对于普通文件,这可以正常工作: for i in `find devel/ -newer $UPLOAD_FILE` do echo "Upload:" $i if [ -d $i ] then echo "Creating directory" $i ssh $USER@$SERVER "cd ${REMOTE_PATH}; mkdir -p $i" continue f
for i in `find devel/ -newer $UPLOAD_FILE`
do
echo "Upload:" $i
if [ -d $i ]
then
echo "Creating directory" $i
ssh $USER@$SERVER "cd ${REMOTE_PATH}; mkdir -p $i"
continue
fi
if scp -Cp $i $USER@$SERVER:$REMOTE_PATH/$i
then
echo "$i OK"
else
echo "$i NOK"
rm ${UPLOAD_FILE}_tmp
fi
done
唯一的问题是,对于名称中有空格的文件,for循环失败,因此我将第一行替换为:
find devel/ -newer $UPLOAD_FILE | while read i
do
echo "Upload:" $i
if [ -d $i ]
then
echo "Creating directory" $i
ssh $USER@$SERVER "cd ${REMOTE_PATH}; mkdir -p $i"
continue
fi
if scp -Cp $i $USER@$SERVER:$REMOTE_PATH/$i
then
echo "$i OK"
else
echo "$i NOK"
rm ${UPLOAD_FILE}_tmp
fi
done
出于某种奇怪的原因,ssh命令中断了while循环,因此可以创建第一个缺失的目录,但忽略所有后续缺失的文件/目录
我想这与ssh向stdout写入一些东西有关,这会混淆“read”命令。注释掉ssh命令可以使循环正常工作
有人知道为什么会发生这种情况,以及如何防止ssh破坏while循环吗?问题是
ssh
读取标准输入,因此它会吃掉所有剩余的行。您只需将其标准输入连接到以下位置:
ssh $USER@$SERVER "cd ${REMOTE_PATH}; mkdir -p $i" < /dev/null
ssh$USER@$SERVER“cd${REMOTE_PATH};mkdir-p$i”
您还可以使用ssh-n来代替重定向。另一种方法是在除stdin之外的FD上循环:
while IFS= read -u 3 -r -d '' filename; do
if [[ -d $filename ]]; then
printf -v cmd_str 'cd %q; mkdir -p %q' "$REMOTE_PATH" "$filename"
ssh "$USER@$SERVER" "$cmd_str"
else
printf -v remote_path_str '%q@%q:%q/%q' "$USER" "$SERVER" "$REMOTE_PATH" "$filename"
scp -Cp "$filename" "$remote_path_str"
fi
done 3< <(find devel/ -newer "$UPLOAD_FILE" -print0)
而IFS=read-u3-r-d“”文件名;做
如果[-d$filename]];然后
printf-v cmd_str'cd%q;mkdir-p%q'$REMOTE_路径'$filename'
ssh“$USER@$SERVER”“$cmd_str”
其他的
printf-v remote_path_str“%q@%q:%q/%q'$USER”“$SERVER”“$remote_path”“$filename”
scp-Cp“$filename”“$remote\u path\u str”
fi
Done3<您也可以使用ssh-n来完成同样的事情。顺便说一句,这是一个相当多的bug。如果$1
是一个带空格的文件名怎么办?您最终会创建多个目录。类似地,对于$REMOTE\u路径
printf%q
可用于引用变量,以便安全地通过ssh调用的额外shell传递。谢谢:在我注意到问题是使用ssh而不是脚本的另一部分执行命令之前,我进行了一些调试。您能详细说明一下从stdin读取ssh是什么意思吗?我尝试了“ssh$USER@$SERVER”一些命令;echo“blabla”"; 而且效果很好,所以我不明白它到底是什么意思?救生员。。。这让我困惑了好几个小时……作为旁白——所有大写变量名都是按照惯例为环境变量和内置变量保留的;它们不应用于脚本的本地变量。读取时
如果文件名包含文字反斜杠,则会严重中断。更安全地使用read-r
。类似地,read
将从名称中去除尾随空格;为了避免这种情况,您需要清除IFS
。另外,find | while read
会发出一个以换行符分隔的流,但是UNIX上的合法文件名允许包含换行符。想想如果有人执行了一个mkdir-p devel/$'\n'/etc
,然后写入devel/$'\n'/etc/passwd
,会发生什么情况;此时,您最好希望您的脚本没有权限写入远程计算机上的/etc/passwd
。此外,如果[-d$i]
包含空格或通配符表达式,或者是空的,则[-d$i]
将出现错误。使用带有引号的[[-d$i]]
(如果您的shell是bash或其他ksh衍生产品)或[-d“$i”]
(为了POSIX兼容性)。我刚才发现了这个问题,只想指出,只有当ssh
成功与远程计算机建立连接时,才会出现错误情况。当连接被拒绝时,不会发生这种情况。