简体   繁体   English

使用bash脚本输入ssh密码,无此文件或目录

[英]Enter ssh password using bash script, No such file or directory

I have many servers with the same password. 我有许多使用相同密码的服务器。 I want to scp the same files in all of my servers. 我想在所有服务器中保存相同的文件。 To do this i wrote script but doesn't work properly? 为此,我编写了脚本,但无法正常工作? Is it correct? 这是正确的吗? how can I do it? 我该怎么做?

#!/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

The result is: 结果是:

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

I don't know how it is possible thank you in advance 我不知道怎么可能先谢谢你

Here are a few recommendations: 以下是一些建议:

  • You can always echo line in your shell script to see what's going on. 您总是可以在shell脚本中回显line以查看发生了什么。
  • You can also use set -xv to help you debug a shell script. 您还可以使用set -xv来帮助调试Shell脚本。 Simply put set -xv before the part you want to debug, and set +xv to turn off the debug. 只需将set -xv放在要调试的部分之前,然后set +xv为关闭调试即可。 You can also use export PS4="\\$LINENO> " to print out the line number in your shell script. 您也可以使用export PS4="\\$LINENO> "在shell脚本中打印export PS4="\\$LINENO> "号。

Here's how your script will look with the set -xv . 这是使用set -xv脚本的外观。 It's a really nice tool for debugging shell scripts. 这是调试shell脚本的非常好的工具。 Use it: 用它:

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

I simply made the sshpass command echo statements since the program wouldn't work on my system anyway. 我只是做了sshpass命令echo语句,因为该程序无论如何都无法在我的系统上运行。 Here's my output with echo . 这是我的输出与echo This is the command you're trying to execute: 这是您要执行的命令:

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/

First, that IP address is all wrong. 首先,该IP地址是错误的。 You notice you seem to be looping, because the command is being executed the number of times you expect, but you're using the wrong variable for the IP address in the command. 您会发现您似乎在循环,因为命令的执行次数是您期望的,但是您在命令IP地址中使用了错误的变量。 You have: 你有:

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

and not: 并不是:

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

Note that $ip1 is your looping variable and $IP1 is the variable that contains all of your IP addresses. 请注意, $ip1是循环变量,而$IP1是包含所有IP地址的变量。 Don't call your variables by the same name that differ in case! 请勿使用大小写不同的相同名称来调用变量! . It would have been better if you gave them each different names. 如果您给他们分别使用不同的名称,那就更好了。 For example $ip_list1 instead of $IP1 and $ip instead of $ip1 : 例如,用$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

Correcting for that issue, I get: 纠正该问题,我得到:

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/

See the problem now? 现在看到问题了吗? You're directory that you're scping to is not correct. 您正在scping目录不正确。 It looks like you want to send your file to multiple directories, and assuming that somehow the scp command will loop through itself. 看起来您想将文件发送到多个目录,并假设scp命令将以某种方式循环通过自身。

Here's my version of your program. 这是我的程序版本。 I added an inner loop to go through each directory for each IP address: 我添加了一个内部循环来遍历每个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

You don't need to set the IP list and directory list on multiple lines because the for will break the variable on white space. 您不需要在多行上设置IP列表和目录列表,因为for会在空白处破坏变量。 This is both a blessing and a curse. 这既是福也是祸。 Or, better might leave you cursing if you're not careful. 或者,如果您不小心的话,最好还是骂自己。 You have to make sure that there are no unintended white spaces. 您必须确保没有意外的空格。

The output is now a more reasonable: 现在的输出更加合理:

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/

Remove the echo and it should now work. 删除echo ,它现在应该可以工作了。

It appears that you expect Bash to loop over one line at a time of your multi-line variables, but that is not at all how it works. 您似乎希望Bash一次在多行变量中循环一行,但这完全不是它的工作原理。 A string is a string and a string with newlines in it is still just a string. 字符串是一个字符串,其中包含换行符的字符串仍然只是一个字符串。 You can loop over the tokens (words) in an unquoted string but there is no simple way to index into strings of the same length, as you are apparently trying to do (implicitly). 您可以在未加引号的字符串中循环标记(单词),但是没有一种简单的方法可以索引到相同长度的字符串中,因为您显然想这样做(隐式)。

You could use Bash arrays instead: 您可以改用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

or you could use a simple list of parameters and a here document: 或者您可以使用简单的参数列表和此处文档:

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

I tend to prefer the latter approach both as more readable and more portable. 我倾向于选择后一种方法,因为它更具可读性和便携性。 If you want to update the list, the server IP and the path are kept together, so you don't have to keep track of the index into each array (this is trivial for an array with four elements, but a real hassle the more you grow past half a dozen or so, and/or more than about two or three arrays). 如果要更新列表,服务器IP和路径将保持在一起,因此您不必跟踪每个数组的索引(这对于包含四个元素的数组来说是微不足道的,但实际麻烦多了)您会成长超过六打左右,和/或超过两到三个阵列)。 This syntax is portable all the way back to the original v7 Bourne shell , so it works where (a modern version of) Bash is not available. 此语法可移植到最初的v7 Bourne shell ,因此可以在没有Bash(现代版本)的地方使用。

(For your amusement, see how to implement the following with arrays. (为您的娱乐,请参见如何使用数组实现以下内容。

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

... especially as you add more users. ...尤其是当您添加更多用户时。 Or maybe don't.) 或者也许不。)

You can factor out sshpass from this by using public keys (which as such I recommend), but I imagine you will still need to get the logic of this script working in one way or another. 您可以通过使用公共密钥(我建议采用这种方式)将sshpass排除sshpass ,但我想您仍然需要使此脚本的逻辑以一种或另一种方式工作。

Create a key pair and distributed the public key to your servers. 创建一个密钥对 ,并将公共密钥分发到您的服务器。 If you put a password on the private key, then you'll need ssh-agent running with the key loaded. 如果您在私钥上输入密码,则需要在已加载密钥的情况下运行ssh-agent

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM