使用bash脚本输入ssh密码,没有这样的文件或目录



我有很多服务器使用相同的密码。我想在我的所有服务器中scp相同的文件。为了做到这一点,我写了剧本,但不能正常工作?这是正确的吗?我该怎么做?

#!/usr/bin/env bash
export HISTFILE=

IP1="1.1.1.1
2.2.2.2
3.3.3.3
4.4.4.4"
IP2="5.5.5.5
6.6.6.6
6.6.6.6
7.7.7.7"
DIR1="1
2
3
4"
DIR2="5
100
104
135"
for ip1 in $IP1
do
sshpass -fpass1.txt scp -r root@$IP1:/attach/res* /user/path/to/$DIR1/
done
for ip2 in $IP2
do
sshpass -fpass2.txt scp -r root@$IP2:/attach/res* /user/path/to/$DIR2/
done

结果是:

107: No such file or directory
107: No such file or directory
107: No such file or directory
107: No such file or directory
135: No such file or directory
135: No such file or directory
135: No such file or directory
135: No such file or directory

我不知道怎么可能提前感谢

以下是一些建议:

  • 您可以随时回显shell脚本中的行以查看发生了什么
  • 您还可以使用set -xv来帮助调试shell脚本。只需将set -xv放在要调试的部件之前,并将set +xv关闭调试。您也可以使用export PS4="$LINENO> "打印出shell脚本中的行号

以下是使用set -xv时脚本的外观。这是一个非常好的调试shell脚本的工具。使用它:

export PS4="$LINENO: "
set -xv
for ip1 in $IP1
do
sshpass -fpass1.txt scp -r root@$IP1:/attach/res* /user/path/to/$DIR1/
done
for ip2 in $IP2
do
sshpass -fpass2.txt scp -r root@$IP2:/attach/res* /user/path/to/$DIR2/
done
set +xv

我只是简单地做了sshpass命令回显语句,因为该程序无论如何都无法在我的系统上运行。这是我对echo的输出。这是您试图执行的命令:

sshpass -fpass1.txt scp -r root@1.1.1.1 2.2.2.2 3.3.3.3 4.4.4.4:/attach/res* /user/path/to/1 2 3 4/
sshpass -fpass1.txt scp -r root@1.1.1.1 2.2.2.2 3.3.3.3 4.4.4.4:/attach/res* /user/path/to/1 2 3 4/
sshpass -fpass1.txt scp -r root@1.1.1.1 2.2.2.2 3.3.3.3 4.4.4.4:/attach/res* /user/path/to/1 2 3 4/
sshpass -fpass1.txt scp -r root@1.1.1.1 2.2.2.2 3.3.3.3 4.4.4.4:/attach/res* /user/path/to/1 2 3 4/
sshpass -fpass2.txt scp -r root@5.5.5.5 6.6.6.6 6.6.6.6 7.7.7.7:/attach/res* /user/path/to/5 100 104 135/
sshpass -fpass2.txt scp -r root@5.5.5.5 6.6.6.6 6.6.6.6 7.7.7.7:/attach/res* /user/path/to/5 100 104 135/
sshpass -fpass2.txt scp -r root@5.5.5.5 6.6.6.6 6.6.6.6 7.7.7.7:/attach/res* /user/path/to/5 100 104 135/
sshpass -fpass2.txt scp -r root@5.5.5.5 6.6.6.6 6.6.6.6 7.7.7.7:/attach/res* /user/path/to/5 100 104 135/

首先,那个IP地址都错了。您注意到似乎在循环,因为命令的执行次数与您预期的次数相同,但您在命令中使用了错误的IP地址变量。您有:

sshpass -fpass1.txt scp -r root@$IP1:/attach/res* /user/path/to/$DIR1/
^^^^

而不是:

sshpass -fpass1.txt scp -r root@$ip1:/attach/res* /user/path/to/$DIR1/
^^^^

请注意,$ip1是循环变量,$IP1是包含所有IP地址的变量不要用大小写不同的相同名称调用变量。如果你给他们取不同的名字会更好。例如$ip_list1代替$IP1$ip代替$ip1

ip_list1="..."
for ip in $ip_list`
do
sshpass -fpass1.txt scp -r root@$ip:/attach/res* /user/path/to/$DIR1/
done

纠正这个问题,我得到:

sshpass -fpass1.txt scp -r root@1.1.1.1:/attach/res* /user/path/to/1
2
3
4/
sshpass -fpass1.txt scp -r root@2.2.2.2:/attach/res* /user/path/to/1
2
3
4/
sshpass -fpass1.txt scp -r root@3.3.3.3:/attach/res* /user/path/to/1
2
3
4/
sshpass -fpass1.txt scp -r root@4.4.4.4:/attach/res* /user/path/to/1
2
3
4/
sshpass -fpass2.txt scp -r root@5.5.5.5:/attach/res* /user/path/to/5
100
104
135/
sshpass -fpass2.txt scp -r root@6.6.6.6:/attach/res* /user/path/to/5
100
104
135/
sshpass -fpass2.txt scp -r root@6.6.6.6:/attach/res* /user/path/to/5
100
104
135/
sshpass -fpass2.txt scp -r root@7.7.7.7:/attach/res* /user/path/to/5
100
104
135/

现在看到问题了吗?您的scping所在的目录不正确。看起来您想要将文件发送到多个目录,并假设scp命令将以某种方式循环通过它自己。

这是我对你的程序的看法。我添加了一个内部循环来遍历每个IP地址的每个目录:

#!/bin/bash
ip_list1="1.1.1.1   2.2.2.2   3.3.3.3    4.4.4.4" 
ip_list2="5.5.5.5   6.6.6.6   6.6.6.6    7.7.7.7" 
dir_list1="1        2         3          4" 
dir_list2="5        100       104        135" 
for ip in $ip_list1
do
for dir in $dir_list1
do
echo "sshpass -fpass1.txt scp -r root@$ip:/attach/res* /user/path/to/$dir/"
done
done
for ip in $ip_list2
do
for dir in $dir_list2
do
echo "sshpass -fpass2.txt scp -r root@$ip:/attach/res* /user/path/to/$dir/"
done
done

您不需要在多行上设置IP列表和目录列表,因为for会在空白处中断变量。这既是福也是祸。或者,如果你不小心,最好让你诅咒。你必须确保没有意外的空白。

现在的输出更加合理:

sshpass -fpass1.txt scp -r root@1.1.1.1:/attach/res* /user/path/to/1/
sshpass -fpass1.txt scp -r root@1.1.1.1:/attach/res* /user/path/to/2/
sshpass -fpass1.txt scp -r root@1.1.1.1:/attach/res* /user/path/to/3/
sshpass -fpass1.txt scp -r root@1.1.1.1:/attach/res* /user/path/to/4/
sshpass -fpass1.txt scp -r root@2.2.2.2:/attach/res* /user/path/to/1/
sshpass -fpass1.txt scp -r root@2.2.2.2:/attach/res* /user/path/to/2/
sshpass -fpass1.txt scp -r root@2.2.2.2:/attach/res* /user/path/to/3/
sshpass -fpass1.txt scp -r root@2.2.2.2:/attach/res* /user/path/to/4/
sshpass -fpass1.txt scp -r root@3.3.3.3:/attach/res* /user/path/to/1/
sshpass -fpass1.txt scp -r root@3.3.3.3:/attach/res* /user/path/to/2/
sshpass -fpass1.txt scp -r root@3.3.3.3:/attach/res* /user/path/to/3/
sshpass -fpass1.txt scp -r root@3.3.3.3:/attach/res* /user/path/to/4/
sshpass -fpass1.txt scp -r root@4.4.4.4:/attach/res* /user/path/to/1/
sshpass -fpass1.txt scp -r root@4.4.4.4:/attach/res* /user/path/to/2/
sshpass -fpass1.txt scp -r root@4.4.4.4:/attach/res* /user/path/to/3/
sshpass -fpass1.txt scp -r root@4.4.4.4:/attach/res* /user/path/to/4/
sshpass -fpass2.txt scp -r root@5.5.5.5:/attach/res* /user/path/to/5/
sshpass -fpass2.txt scp -r root@5.5.5.5:/attach/res* /user/path/to/100/
sshpass -fpass2.txt scp -r root@5.5.5.5:/attach/res* /user/path/to/104/
sshpass -fpass2.txt scp -r root@5.5.5.5:/attach/res* /user/path/to/135/
sshpass -fpass2.txt scp -r root@6.6.6.6:/attach/res* /user/path/to/5/
sshpass -fpass2.txt scp -r root@6.6.6.6:/attach/res* /user/path/to/100/
sshpass -fpass2.txt scp -r root@6.6.6.6:/attach/res* /user/path/to/104/
sshpass -fpass2.txt scp -r root@6.6.6.6:/attach/res* /user/path/to/135/
sshpass -fpass2.txt scp -r root@6.6.6.6:/attach/res* /user/path/to/5/
sshpass -fpass2.txt scp -r root@6.6.6.6:/attach/res* /user/path/to/100/
sshpass -fpass2.txt scp -r root@6.6.6.6:/attach/res* /user/path/to/104/
sshpass -fpass2.txt scp -r root@6.6.6.6:/attach/res* /user/path/to/135/
sshpass -fpass2.txt scp -r root@7.7.7.7:/attach/res* /user/path/to/5/
sshpass -fpass2.txt scp -r root@7.7.7.7:/attach/res* /user/path/to/100/
sshpass -fpass2.txt scp -r root@7.7.7.7:/attach/res* /user/path/to/104/
sshpass -fpass2.txt scp -r root@7.7.7.7:/attach/res* /user/path/to/135/

卸下echo,它现在应该可以工作了。

您似乎希望Bash一次在多行变量的一行上循环,但这根本不是它的工作方式。字符串是一个字符串,其中包含换行符的字符串仍然只是一个字符串。您可以在未加引号的字符串中循环标记(单词),但没有简单的方法可以索引到相同长度的字符串中,就像您显然试图(隐式)做的那样。

你可以使用Bash数组代替:

IP1=( 1.1.1.1 2.2.2.2 3.3.3.3 4.4.4.4 )
DIR1=( 1 2 3 4 )
for idx in 0 1 2 3; do
sshpass -fpass1.txt scp -r root@"${IP1[$idx]}":/attach/res* /user/path/to/"${DIR1[$idx]}"
done

或者你可以使用一个简单的参数列表和这里的文档:

while read ip dir; do
sshpass -fpass1.txt scp -r root@$ip:/attach/res* /user/path/to/$dir/
done <<____HERE
1.1.1.1  1
2.2.2.2  2
3.3.3.3  3
4.4.4.4  4
____HERE

我倾向于更喜欢后一种方法,因为它更可读,也更便携。如果你想更新列表,服务器IP和路径会放在一起,所以你不必跟踪每个数组的索引(对于一个有四个元素的数组来说,这是微不足道的,但当你超过六个左右,和/或超过两三个数组时,这真的很麻烦)。这种语法可以一直移植到最初的v7 Bourne shell,因此它适用于(现代版本的)Bash不可用的地方。

(为了您的娱乐,请参阅如何使用数组实现以下内容。

while read user home shell groups loc; do
cat <<-____HERE
User:   $user
Home:   $home
Shell:  $shell
Groups: $groups
Loc:    $loc
____HERE
done <<HERE
frodo    /home/shire    /bin/bash dev                   Mordor
bilbo    /home/valinor  /bin/ksh  admin,dev             Undying Lands
maisy    /home/maisy    /bin/zsh  dev                   Mouseville
tallulah /home/tallulah /bin/sh   wheel,admin,dev,deity Dekadenz Kave
HERE

尤其是当您添加更多用户时。或者可能不会。)

您可以通过使用公钥(我建议这样做)从中排除sshpass,但我认为您仍然需要以某种方式使该脚本的逻辑工作。

创建一个密钥对并将公钥分发到服务器。如果你在私钥上加了密码,那么你需要在加载密钥的情况下运行ssh-agent

相关内容

  • 没有找到相关文章

最新更新