You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SSH删除远程文件致Bash脚本while循环意外终止?求原因分析

问题原因与解决方案

这个问题我太熟悉了——根源在于ssh命令会默认占用标准输入,刚好你的while read循环是从标准输入读取find命令的输出,两者直接冲突了!

具体原因

当你第一次循环执行ssh root@$RMT_IP "rm $file"时,ssh会自动从当前的标准输入(也就是find命令输出的文件列表)读取数据,这就把剩下的所有文件路径都“吃掉”了。read命令再也读不到下一个文件路径,循环自然就提前终止,只执行了一次。

快速解决方法

给ssh命令加上-n参数,这个参数会强制ssh不从标准输入读取数据(相当于把标准输入重定向到/dev/null),这样就不会干扰while read的输入流了。修改后的代码行如下:

ssh -n root@$RMT_IP "rm $file"

更安全的进阶优化

另外要注意,如果远程文件的路径包含空格、引号或者其他特殊字符,直接在ssh命令里使用$file可能会导致命令执行出错。推荐用printf %q来对文件路径进行转义,确保命令安全执行:

ssh -n root@$RMT_IP "$(printf 'rm %q' "$file")"

修改后的完整脚本示例

#!/bin/bash
S_ACCOUNTS=('yohplala')
RMT_IP='88.214.320.588'
LOC_PATH_DATA='../data/cs_remote/'
MOD_TIME='+10' # Last modification time, in minutes
# List, copy, delete files.
for serv_account in "${S_ACCOUNTS[@]}"; do
    while IFS= read -r -d $'\0' file; do
        scp -i ~/.ssh/id_rsa root@$RMT_IP:"$file" "$LOC_PATH_DATA""$serv_account"
        if test -f "$LOC_PATH_DATA""$serv_account"/'/'"$(basename "$file")"; then
            echo "$(basename "$file")"' successfully copied.'
            # 加上-n参数避免占用标准输入,同时用printf转义文件路径
            ssh -n root@$RMT_IP "$(printf 'rm %q' "$file")"
        fi
    done < <(ssh root@$RMT_IP "find "/root/test" -maxdepth 1 -type f -mmin $MOD_TIME -print0")
done

内容的提问来源于stack exchange,提问作者pierre_j

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.09 10:22:42