Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/ssh/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
ssh在bash中中断while循环_Bash_Ssh - Fatal编程技术网

ssh在bash中中断while循环

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

我使用此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
    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
成功与远程计算机建立连接时,才会出现错误情况。当连接被拒绝时,不会发生这种情况。