SSH命令传参遇^M隐藏字符,chop/chomp无效致脚本执行失败求助
解决SSH命令中目录变量含^M隐藏字符的问题
核心原因
你遇到的^M是Windows风格的回车符(CR),当读取Windows格式的文件时,每行结尾的CRLF(回车+换行)在Unix环境下会留下单独的CR字符。chomp默认只删除换行符(LF),chop仅删除最后一个字符(如果行尾是CRLF,chop会先删LF,剩下CR),导致变量里仍残留CR,执行cd时被解析成目录名的一部分,自然找不到路径。
解决方案
1. 彻底清除所有换行相关隐藏字符
对读取到的$orig变量执行全局替换,去掉所有CR和LF:
$orig =~ s/[\r\n]+//g;
这个正则会把变量里所有的回车、换行字符全部删除,比chomp/chop更彻底。
2. 验证变量是否清理干净
可以在代码里加调试输出,确认变量没有隐藏字符:
# 用单引号包裹变量,方便查看首尾的隐藏字符 print "Cleaned orig: '$orig'\n"; # 或者用od命令查看二进制内容(shell环境下) system("echo '$orig' | od -c");
如果输出里没有\r或^M,说明清理成功。
3. 修正SSH命令的写法
构造SSH命令时,用引号包裹远程执行的命令,避免字符解析混乱,同时确保cd失败后不会继续执行脚本:
my $ssh_command = qq{ssh $target_server "cd '$orig' && ./AddAlias.pl"}; # 执行命令 system($ssh_command);
用&&连接cd和脚本执行,只有cd成功时才会运行AddAlias.pl,避免出现找不到脚本的误报。
4. 从源头上避免读取隐藏字符
读取文件时,指定转换Windows换行符为Unix格式,用binmode设置文件句柄的换行模式:
open(my $fh, '<', 'servers.txt') or die "Failed to open file: $!"; # 自动将CRLF转换为LF binmode($fh, ':crlf'); while (my $line = <$fh>) { chomp $line; # 此时只会删除LF,变量里没有CR push @orig_dirs, $line; } close $fh;
内容的提问来源于stack exchange,提问作者Jacob Boyce
相关产品推荐
相关产品推荐

