2014-01-14 166 views
1

我有许多具有相同密码的服务器。 我想在所有服务器上scp相同的文件。 要做到这一点,我写了脚本,但不能正常工作? 这是正确的吗?我该怎么做?使用bash脚本输入ssh密码,没有这样的文件或目录

#!/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 [email protected]$IP1:/attach/res* /user/path/to/$DIR1/ 

done 

for ip2 in $IP2 
do 

    sshpass -fpass2.txt scp -r [email protected]$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 

我不知道它是如何可能 预先感谢您

+1

任何使用'ssh-copy-id'大量部署密钥的机会,然后定期用普通的scp复制? – cnicutar

+0

我不明白......你可以用这种方式改变我的剧本吗? – MLSC

+0

阅读openssh公钥,然后搜索'ssh-copy-id'。它会变得很明显:-) – cnicutar

回答

2

看来你期望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 [email protected]"${IP1[$idx]}":/attach/res* /user/path/to/"${DIR1[$idx]}" 
done 

或者你可以使用的参数的简单列表,并立即文档:

while read ip dir; do 
    sshpass -fpass1.txt scp -r [email protected]$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从这个通过使用公钥(这是我推荐),但我想你仍然需要得到这个脚本的逻辑工作在这种或那种方式。

+0

其实,这工作正常。做一个测试。创建一个多行变量并将其传递给for循环。 –

+0

非常感谢你..我正在关闭..但有一个错误:(ssh:无法解析主机名:名称或服务未知) – MLSC

+0

while方法正常工作:) ...谢谢亲爱的朋友 – MLSC

1

Create a key pair和分布式的公共密钥服务器。如果您在私钥上输入密码,则需要在加载密钥的情况下运行ssh-agent

+0

你的意思是我没有通过ssh-key输入密码吗? – MLSC

+0

我的意思是,SCP总是要求输入密码。为了避免这种情况,请设置ssh密钥。当您设置ssh密钥时,您可以选择在私钥上加密码(对其进行加密)。如果您选择这样做,那么您需要运行加密私钥的'ssh-agent'才能运行脚本。 –

3

这里有几个建议:

  • 你可以在你的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 [email protected]$IP1:/attach/res* /user/path/to/$DIR1/ 
done 

for ip2 in $IP2 
do 
    sshpass -fpass2.txt scp -r [email protected]$IP2:/attach/res* /user/path/to/$DIR2/ 
done 
set +xv 

我只是做了sshpass命令echo语句,因为该计划将不是我的系统上运行反正。这是我的输出echo。这是您尝试执行的命令:

sshpass -fpass1.txt scp -r [email protected] 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 [email protected] 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 [email protected] 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 [email protected] 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 [email protected] 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 [email protected] 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 [email protected] 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 [email protected] 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 [email protected]$IP1:/attach/res* /user/path/to/$DIR1/ 
           ^^^^ 

,而不是:

sshpass -fpass1.txt scp -r [email protected]$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 [email protected]$ip:/attach/res* /user/path/to/$DIR1/ 
done 

修正这个问题,我得到:

sshpass -fpass1.txt scp -r [email protected]:/attach/res* /user/path/to/1 
2 
3 
4/ 
sshpass -fpass1.txt scp -r [email protected]:/attach/res* /user/path/to/1 
2 
3 
4/ 
sshpass -fpass1.txt scp -r [email protected]:/attach/res* /user/path/to/1 
2 
3 
4/ 
sshpass -fpass1.txt scp -r [email protected]:/attach/res* /user/path/to/1 
2 
3 
4/ 
sshpass -fpass2.txt scp -r [email protected]:/attach/res* /user/path/to/5 
100 
104 
135/ 
sshpass -fpass2.txt scp -r [email protected]:/attach/res* /user/path/to/5 
100 
104 
135/ 
sshpass -fpass2.txt scp -r [email protected]:/attach/res* /user/path/to/5 
100 
104 
135/ 
sshpass -fpass2.txt scp -r [email protected]:/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 [email protected]$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 [email protected]$ip:/attach/res* /user/path/to/$dir/" 
    done 
done 

你并不需要设置多条线路上的IP列表和目录列表,因为for会打破白色空间的变量。这既是祝福也是诅咒。或者,如果你不小心,最好可能会让你咒骂。你必须确保没有意外的空白。

输出现在是一个比较合理的:

sshpass -fpass1.txt scp -r [email protected]:/attach/res* /user/path/to/1/ 
sshpass -fpass1.txt scp -r [email protected]:/attach/res* /user/path/to/2/ 
sshpass -fpass1.txt scp -r [email protected]:/attach/res* /user/path/to/3/ 
sshpass -fpass1.txt scp -r [email protected]:/attach/res* /user/path/to/4/ 
sshpass -fpass1.txt scp -r [email protected]:/attach/res* /user/path/to/1/ 
sshpass -fpass1.txt scp -r [email protected]:/attach/res* /user/path/to/2/ 
sshpass -fpass1.txt scp -r [email protected]:/attach/res* /user/path/to/3/ 
sshpass -fpass1.txt scp -r [email protected]:/attach/res* /user/path/to/4/ 
sshpass -fpass1.txt scp -r [email protected]:/attach/res* /user/path/to/1/ 
sshpass -fpass1.txt scp -r [email protected]:/attach/res* /user/path/to/2/ 
sshpass -fpass1.txt scp -r [email protected]:/attach/res* /user/path/to/3/ 
sshpass -fpass1.txt scp -r [email protected]:/attach/res* /user/path/to/4/ 
sshpass -fpass1.txt scp -r [email protected]:/attach/res* /user/path/to/1/ 
sshpass -fpass1.txt scp -r [email protected]:/attach/res* /user/path/to/2/ 
sshpass -fpass1.txt scp -r [email protected]:/attach/res* /user/path/to/3/ 
sshpass -fpass1.txt scp -r [email protected]:/attach/res* /user/path/to/4/ 
sshpass -fpass2.txt scp -r [email protected]:/attach/res* /user/path/to/5/ 
sshpass -fpass2.txt scp -r [email protected]:/attach/res* /user/path/to/100/ 
sshpass -fpass2.txt scp -r [email protected]:/attach/res* /user/path/to/104/ 
sshpass -fpass2.txt scp -r [email protected]:/attach/res* /user/path/to/135/ 
sshpass -fpass2.txt scp -r [email protected]:/attach/res* /user/path/to/5/ 
sshpass -fpass2.txt scp -r [email protected]:/attach/res* /user/path/to/100/ 
sshpass -fpass2.txt scp -r [email protected]:/attach/res* /user/path/to/104/ 
sshpass -fpass2.txt scp -r [email protected]:/attach/res* /user/path/to/135/ 
sshpass -fpass2.txt scp -r [email protected]:/attach/res* /user/path/to/5/ 
sshpass -fpass2.txt scp -r [email protected]:/attach/res* /user/path/to/100/ 
sshpass -fpass2.txt scp -r [email protected]:/attach/res* /user/path/to/104/ 
sshpass -fpass2.txt scp -r [email protected]:/attach/res* /user/path/to/135/ 
sshpass -fpass2.txt scp -r [email protected]:/attach/res* /user/path/to/5/ 
sshpass -fpass2.txt scp -r [email protected]:/attach/res* /user/path/to/100/ 
sshpass -fpass2.txt scp -r [email protected]:/attach/res* /user/path/to/104/ 
sshpass -fpass2.txt scp -r [email protected]:/attach/res* /user/path/to/135/ 

取出echo,它现在应该工作。

+0

优秀的大卫......谢谢..我会做到的... – MLSC

相关问题