首页 > 解决方案 > Bash:`sshpass`命令在嵌套的while循环中无法按预期工作

问题描述

我对 bash 脚本完全陌生。我正在尝试编写一个 bash 脚本来将文件从登台复制到多个生产服务器。

我正在使用三个文件。

  1. serverPass.txt :包含多个服务器 ip 及其密码(空格分隔)。

  2. path.txt :包含需要在每个服务器上复制文件的路径serverPass.txt

  3. copy.sh :bash 脚本文件。

复制.sh:

#!/bin/bash
 while read SERVER PASSWORD;
 do
     while read PATH;
     do
         sshpass -p "$PASSWORD" scp * "$SERVER":"$PATH"
     done <./paths.txt  
 done <./serverPass.txt

我得到的输出是:

sshpass: command not found

但是 sshpass 已经安装好,直接在命令行中使用时可以正常工作。我究竟做错了什么?

whereis和的输出which

dmtntimespacedev1:/usr/local/tempcheck/Test # whereis sshpass
sshpass: /usr/bin/sshpass /usr/share/man/man1/sshpass.1.gz
dmtntimespacedev1:/usr/local/tempcheck/Test # which sshpass
/usr/bin/sshpass

标签: bash

解决方案


while read PATH;

是一个特殊的PATH变量。来自POSIX shell 手册

小路

按照 IEEE Std 1003.1-2001 第 8 章“环境变量”的基本定义卷中所述格式化的字符串,用于影响命令解释;请参阅命令搜索和执行。

...

命令搜索和执行

.... 应使用 PATH 环境变量搜索命令 ....

PATH环境变量指定搜索命令的路径。我的系统上的示例PATH等于:

/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/lib/jvm/default/bin:/usr/bin/site_perl:/usr/bin/vendor_perl:/usr/bin/core_perl:/bin:/sbin:/home/kamil/bin

这些是我的命令所在的路径。路径用 . 分隔:

当您这样做时,您会while read PATH用其他字符串覆盖 PATH 环境变量,因此无法找到您的命令。

更改变量的名称。在 shell 中将导出的变量设为大写是很常见的。脚本中未导出的变量通常使用小写字母。还可以将-r选项与 read 一起使用,以便\反斜杠不特殊,并指定IFS=您是否不想从行中删除前导和尾随空格(如果您想这样做,不知道)。您修复的脚本可能如下所示:

#!/bin/bash
 while read -r server password; do
     while read -r path; do
         sshpass -p "$password" scp * "$server":"$path" </dev/null
     done <./paths.txt  
 done <./serverPass.txt

推荐阅读