【问题标题】:Automatically enter SSH password with script使用脚本自动输入 SSH 密码
【发布时间】:2012-08-25 12:26:42
【问题描述】:

我需要创建一个脚本,自动将密码输入到 OpenSSH ssh 客户端。

假设我需要使用密码a1234b SSH 到myname@somehost

我已经试过了……

#~/bin/myssh.sh
ssh myname@somehost
a1234b

...但这不起作用。

如何将这个功能加入到脚本中?

【问题讨论】:

    标签: linux shell ssh openssh


    【解决方案1】:

    首先你需要安装sshpass

    • Ubuntu/Debian:apt-get install sshpass
    • Fedora/CentOS:yum install sshpass
    • 拱门:pacman -S sshpass

    示例:

    sshpass -p "YOUR_PASSWORD" ssh -o StrictHostKeyChecking=no YOUR_USERNAME@SOME_SITE.COM
    

    自定义端口示例:

    sshpass -p "YOUR_PASSWORD" ssh -o StrictHostKeyChecking=no YOUR_USERNAME@SOME_SITE.COM:2400
    

    注意事项:

    • sshpass 也可以在传递-f 标志时从文件中读取密码。
      • 使用-f 可防止在执行ps 命令时密码可见。
      • 存储密码的文件应具有安全权限。

    【讨论】:

    • 这比使用 Expect 好很多。
    • 请注意,虽然 sshpass 会阻止您的密码来自 ps -aux 等命令,但您通常不应通过输入密码来运行命令,因为同一台计算机上的其他用户可能会通过以下方式查看密码运行ps -aux。如果可行,您还想改用公钥身份验证,如另一个答案中所述。这使您可以将身份验证信息与脚本分开,这样您就可以放心地与其他人共享您的脚本,然后决定在您的 ~/.ssh 文件夹上启用加密而不加密您的脚本。
    • 不幸的是,这在具有自定义 ssh 端口的服务器上对我不起作用...为什么 ssh 不能只给我们在命令行中插入密码的选项?
    • 为了自定义端口工作在命令末尾添加“-p port-number”
    【解决方案2】:

    在寻找这个问题的答案几个月后,我终于找到了一个更好的解决方案:编写一个简单的脚本。

    #!/usr/bin/expect
    
    set timeout 20
    
    set cmd [lrange $argv 1 end]
    set password [lindex $argv 0]
    
    eval spawn $cmd
    expect "password:"
    send "$password\r";
    interact
    

    发给/usr/bin/exp,这样就可以使用了:

    • exp <password> ssh <anything>
    • exp <password> scp <anysrc> <anydst>

    完成!

    【讨论】:

    • 这个答案应该得到更多的选票,它是一个很好的包装。刚刚尝试了一些常见的操作,例如使用各种标志进行 rsync 和远程命令执行,并且每次都有效。添加到我的有用脚本工具箱中,谢谢@damn_c!
    • 也许因为人们没有预料到它没有得到更多的支持?
    • IMO 之所以不是一个很好的答案,是因为密码是写在脚本中的,这是迄今为止最不安全的方法......
    • 任何在机器上运行 ps 的人都可以看到密码。
    • "assword" 太棒了:-)
    【解决方案3】:

    使用公钥认证:https://help.ubuntu.com/community/SSH/OpenSSH/Keys

    在源主机中只运行一次:

    ssh-keygen -t rsa # ENTER to every field
    ssh-copy-id myname@somehost
    

    就是这样,之后你就可以在没有密码的情况下进行ssh了。

    【讨论】:

    • 我明白了。但我需要使用密码进行 ssh。这是因为,“我”可能将脚本放在拇指驱动器上,并且需要从任何计算机上运行它;同时不禁用密码需求。
    • @user1467855,我认为您需要更好地解释您的要求。没有人建议您使用不安全的网络。在公钥方法中,用户仍然可以使用密码登录。但是您会将私钥复制到您的 U 盘上,这意味着 U 盘将是唯一无需密码即可登录的设备。
    • 不幸的是,我处于 ​​OP 状态,因为系统管理员不允许通过 rsa/dsa 密钥进行身份验证并且需要密码。你要做什么。
    • 投反对票,因为这甚至没有尝试回答所提出的实际问题。
    • 这仍然提示首次登录,不能在脚本中使用!
    【解决方案4】:

    您可以使用期望脚本。我已经很久没有写过一篇了,但它应该如下所示。您需要使用 #!/usr/bin/expect 来领导脚本

    #!/usr/bin/expect -f
    spawn ssh HOSTNAME
    expect "login:" 
    send "username\r"
    expect "Password:"
    send "password\r"
    interact
    

    【讨论】:

    • 我按照你的建议做了,但收到以下错误:/bin/myssh.sh: 2: spawn: not found /bin/myssh.sh: 3: expect: not found /bin/myssh.sh: 4: send: not found /bin/myssh.sh: 5: expect: not found /bin/myssh.sh: 6: send: not found
    • 感谢 Aaron 将我的答案修改为正确。你可能需要运行下面的命令来找到正确的路径来为 expect.which expect
    • 你也可以使用这个shebang line:#!/usr/bin/env expect
    • 我在末尾添加了interact,因此 ssh 会话实际上是交互式的
    • @AaronDigulla,这怎么比任何替代方案都不安全,例如私钥也是可读的?也许我们应该建议脚本只能由用户阅读?
    【解决方案5】:

    变体 I

    sshpass -p PASSWORD ssh USER@SERVER
    

    变体 II

    #!/usr/bin/expect -f
    spawn ssh USERNAME@SERVER "touch /home/user/ssh_example"
    expect "assword:"
    send "PASSWORD\r"
    interact
    

    【讨论】:

    • 没有。 sshpass 不是 ssh。 SYNOPSIS sshpass [-ffilename|-dnum|-ppassword|-e] [options] command arguments
    • 为了在 Linux CentOS 中运行 sshpass,你必须先yum -y install epel-release 然后yum -y install sshpass
    • 在这个上下文中这个数据可以忽略
    • 虽然我知道这是一篇旧文章,但值得注意的是,Variant II 方法会使会话的密码在 bash 历史记录中易受攻击,因此非常不可取。
    【解决方案6】:

    sshpass + autossh

    已经提到的sshpass 的一个不错的好处是您可以将它与autossh 一起使用,从而消除更多的交互效率低下。

    sshpass -p mypassword autossh -M0 -t myusername@myserver.mydomain.com
    

    这将允许自动重新连接,例如关闭笔记本电脑会中断 wifi。

    【讨论】:

    • 请注意,您不能在此组合中将选项 -f 添加到 autossh,因为 when used with autossh, ssh will be *unable* to ask for passwords or passphrases. harding.motd.ca/autossh/README.txt 也是 superuser.com/questions/1278583/…
    • 这个 似乎 开始工作,但由于 -M0 标志禁用监控我的连接在一段时间后失败,autossh 没有意识到它;如果我省略该标志,那么它也可以工作,直到连接失败,此时我的密码被服务器拒绝
    【解决方案7】:

    sshpass 具有更好的安全性

    我在寻找一种通过 ssh 进入陷入困境的服务器的方法时偶然发现了这个线程——处理 SSH 连接尝试花了一分钟多的时间,并且在我输入密码之前就超时了。在这种情况下,我希望能够在提示可用时立即提供我的密码。

    (如果不是很清楚:如果服务器处于这种状态,那么设置公钥登录为时已晚。)

    sshpass 来救援。但是,有比sshpass -p 更好的方法来解决这个问题。

    我的实现直接跳到交互式密码提示(不会浪费时间查看是否可以进行公钥交换),并且从不以纯文本形式显示密码。

    #!/bin/sh
    # preempt-ssh.sh
    # usage: same arguments that you'd pass to ssh normally
    echo "You're going to run (with our additions) ssh $@"
    
    # Read password interactively and save it to the environment
    read -s -p "Password to use: " SSHPASS 
    export SSHPASS
    
    # have sshpass load the password from the environment, and skip public key auth
    # all other args come directly from the input
    sshpass -e ssh -o PreferredAuthentications=keyboard-interactive -o PubkeyAuthentication=no "$@"
    
    # clear the exported variable containing the password
    unset SSHPASS
    

    【讨论】:

    • 自我注意:更新脚本以使用trap 以防止ctrl-C 泄漏SSHPASS 变量
    • 我发现PreferredAuthentications=keyboard-interactive 不起作用,但是用PreferredAuthentications=password 替换它起作用了。
    • 我再次在远程机器中运行ssh,使用相同的密码。现在我正在使用export SSHPASS=$SSHPASSSSHPASS 导出到远程机器中。有没有更安全的方法?为了提供一些上下文,我 ssh 进入一个机器集群,设置 ssh 密钥,然后将它们分发到集群中的其他计算机。所有这些都从单台计算机中的脚本运行。所以我需要2级ssh
    • 此解决方案仅适用于您没有事先访问机器以设置基于密钥的登录的情况。我会看看密钥转发dev.to/levivm/…
    【解决方案8】:

    我认为我没有看到任何人建议这样做,而 OP 只是说“脚本”所以......

    我需要解决同样的问题,而我最熟悉的语言是 Python。

    我使用了 paramiko 库。此外,我还需要使用sudo 发出需要升级权限的命令。事实证明 sudo 可以通过“-S”标志通过标准输入接受其密码!见下文:

    import paramiko
    
    ssh_client = paramiko.SSHClient()
    
    # To avoid an "unknown hosts" error. Solve this differently if you must...
    ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    
    # This mechanism uses a private key.
    pkey = paramiko.RSAKey.from_private_key_file(PKEY_PATH)
    
    # This mechanism uses a password.
    # Get it from cli args or a file or hard code it, whatever works best for you
    password = "password"
    
    ssh_client.connect(hostname="my.host.name.com",
                           username="username",
                           # Uncomment one of the following...
                           # password=password
                           # pkey=pkey
                           )
    
    # do something restricted
    # If you don't need escalated permissions, omit everything before "mkdir"
    command = "echo {} | sudo -S mkdir /var/log/test_dir 2>/dev/null".format(password)
    
    # In order to inspect the exit code
    # you need go under paramiko's hood a bit
    # rather than just using "ssh_client.exec_command()"
    chan = ssh_client.get_transport().open_session()
    chan.exec_command(command)
    
    exit_status = chan.recv_exit_status()
    
    if exit_status != 0:
        stderr = chan.recv_stderr(5000)
    
    # Note that sudo's "-S" flag will send the password prompt to stderr
    # so you will see that string here too, as well as the actual error.
    # It was because of this behavior that we needed access to the exit code
    # to assert success.
    
        logger.error("Uh oh")
        logger.error(stderr)
    else:
        logger.info("Successful!")
    

    希望这对某人有所帮助。我的用例是一次在大约 300 台服务器上创建目录、发送和解压缩文件以及启动程序。因此,自动化至关重要。我试过sshpassexpect,然后想出了这个。

    【讨论】:

      【解决方案9】:
      # create a file that echo's out your password .. you may need to get crazy with escape chars or for extra credit put ASCII in your password...
      echo "echo YerPasswordhere" > /tmp/1
      chmod 777 /tmp/1
      
      # sets some vars for ssh to play nice with something to do with GUI but here we are using it to pass creds.
      export SSH_ASKPASS="/tmp/1"
      export DISPLAY=YOURDOINGITWRONG
      setsid ssh root@owned.com -p 22
      

      参考:https://www.linkedin.com/pulse/youre-doing-wrong-ssh-plain-text-credentials-robert-mccurdy?trk=mp-reader-card

      【讨论】:

      • 我认为这篇文章只是在讽刺!
      • 讽刺吧?但是,如果您正在配置它们,那么如果尝试使用默认 admin 对系统进行自动化处理,这很好
      【解决方案10】:

      这是我登录服务器的方式:

      ssp <server_ip>
      
      • alias ssp='/home/myuser/Documents/ssh_script.sh'
      • cat /home/myuser/Documents/ssh_script.sh

      ssp:

      #!/bin/bash
      
      sshpass -p mypassword ssh root@$1
      

      因此:

      ssp server_ip
      

      【讨论】:

        【解决方案11】:

        如果您在 Windows 系统上执行此操作,则可以使用 Plink(PuTTY 的一部分)。

        plink your_username@yourhost -pw your_password
        

        【讨论】:

        • 对于自动脚本,不要忘记选项“-no-antispoof”,否则控制台将等待消息“授予访问权限。按 Return 开始会话。”。要执行的命令应该放在最后:plink your_username@yourhost -pw your_password -no-antispoof your_command
        • 迄今为止 Windows 用户的最佳答案。
        【解决方案12】:

        我正在使用以下解决方案,但为此您必须安装 sshpass 如果尚未安装,请使用 sudo apt install sshpass 安装它

        现在你可以这样做了,

        sshpass -p *YourPassword* shh root@IP

        您也可以创建一个 bash 别名,这样您就不必一次又一次地运行整个命令。 请按照以下步骤操作

        cd ~

        sudo nano .bash_profile

        在文件末尾添加以下代码

        mymachine() { sshpass -p *YourPassword* shh root@IP }

        source .bash_profile

        现在只需从终端运行mymachine 命令,您将无需密码提示进入您的机器。

        注意:

        1. mymachine 可以是您选择的任何命令。
        2. 如果在此任务中安全性对您而言并不重要,并且您只想自动化工作,则可以使用此方法。

        【讨论】:

        • 请注意,.bash_profile 通常是文字可读的。所以把你的密码放在那里不是一个好主意。
        • 感谢@MartinPrikryl 解决了这个问题,我已经更新了最后的注释,所以任何使用这个解决方案的人都知道密码很容易阅读。
        【解决方案13】:

        这基本上是 abbotto 答案的扩展,有一些额外的步骤(针对初学者)可以让你从你的 linux 主机启动你的服务器变得非常容易:

        1. 编写一个简单的 bash 脚本,例如:
        #!/bin/bash
        
        sshpass -p "YOUR_PASSWORD" ssh -o StrictHostKeyChecking=no YOUR_USERNAME@SOME_SITE.COM
        
        1. 保存文件,例如'startMyServer',然后通过在终端中运行它来使文件可执行:
        sudo chmod +x startMyServer
        
        1. 将文件移动到“PATH”变量中的文件夹(在终端中运行“echo $PATH”以查看这些文件夹)。因此,例如将其移至“/usr/bin/”。

        瞧,现在您可以通过在终端中输入“startMyServer”来进入您的服务器。

        附: (1) 这不是很安全,请查看 ssh 密钥以获得更好的安全性。

        附: (2) SMshrimant 的答案非常相似,对某些人来说可能更优雅。但我个人更喜欢使用 bash 脚本。

        【讨论】:

          【解决方案14】:

          我的工作如下

          .ssh/config 被修改以消除是/否提示 - 我在防火墙后面,所以我不担心被欺骗的 ssh 密钥

          host *
               StrictHostKeyChecking no
          

          为期望创建响应文件,即 answer.expect

          set timeout 20
          set node [lindex $argv 0]
          spawn ssh root@node service hadoop-hdfs-datanode restart
          
          expect  "*?assword {
                send "password\r"   <- your password here.
          
          interact
          

          创建你的 bash 脚本并在文件中调用 expect

          #!/bin/bash
          i=1
          while [$i -lt 129]    # a few nodes here
          
            expect answer.expect hadoopslave$i
          
            i=[$i + 1]
            sleep 5
          
          done
          

          使用新配置刷新 128 个 hadoop 数据节点 - 假设您为 hadoop/conf 文件使用 NFS 挂载

          希望这对某人有所帮助 - 我是 Windows 笨蛋,我花了大约 5 个小时才弄明白!

          【讨论】:

          • “我在防火墙后面,所以我不担心被欺骗的 ssh 密钥”。在这种情况下,防火墙完全不做任何事情。 HostKeyCheck 是为了让您可以验证另一端的主机不是木马主机。 IE。一个只是假装是你想要连接的地方。如果您连接到未知主机并执行敏感操作,例如编写具有凭据或令牌的文件或输入密码,则该信息现在实际上是公共知识。你在防火墙后面是无关紧要的。
          【解决方案15】:

          我有一个更好的解决方案,包括使用您的帐户登录,而不是更改为 root 用户。 这是一个 bash 脚本

          http://felipeferreira.net/index.php/2011/09/ssh-automatic-login/

          【讨论】:

            【解决方案16】:

            @abbotto 的答案对我不起作用,不得不做一些不同的事情:

            1. yum install sshpass 改为 -rpm -ivh http://dl.fedoraproject.org/pub/epel/6/x86_64/sshpass-1.05-1.el6.x86_64.rpm
            2. 使用 sshpass 的命令改为 -sshpass -p "pass" ssh user@mysite -p 2122

            【讨论】:

              【解决方案17】:

              我设法让它与它一起工作:

              SSH_ASKPASS="echo \"my-pass-here\""
              ssh -tt remotehost -l myusername
              

              【讨论】:

                【解决方案18】:

                在下面的示例中,我将编写我使用的解决方案:

                场景:我想使用 sh 脚本从服务器复制文件:

                #!/usr/bin/expect
                $PASSWORD=password
                my_script=$(expect -c "spawn scp userName@server-name:path/file.txt /home/Amine/Bureau/trash/test/
                expect \"password:\"
                send \"$PASSWORD\r\"
                expect \"#\"
                send \"exit \r\"
                ")
                
                echo "$my_script"
                

                【讨论】:

                  【解决方案19】:

                  这行得通:

                  #!/usr/bin/expect -f
                  spawn ssh USERNAME@SERVER "touch /home/user/ssh_example"
                  expect "assword:"
                  send "PASSWORD\r"
                  interact
                  

                  但是!!!如果您遇到如下错误,只需使用 expect 启动您的脚本,而不是 bash,如下所示:expect myssh.sh 而不是bash myssh.sh

                  /bin/myssh.sh: 2: spawn: not found /bin/myssh.sh: 3: expect: not found /bin/myssh.sh: 4: send: not found /bin/myssh.sh: 5: expect: not found /bin/myssh.sh: 6: send: not found
                  

                  【讨论】:

                    【解决方案20】:

                    在脚本中使用此脚本 tossh,第一个参数是主机名,第二个参数是密码。

                    #!/usr/bin/expect
                    set pass [lindex $argv 1]
                    set host [lindex $argv 0]
                    spawn ssh -t root@$host echo Hello
                    expect "*assword: " 
                    send "$pass\n";
                    interact"
                    

                    【讨论】:

                    • 这在现有答案之上显示了什么?尤其是damn_c、Lipongo 或 RemiZOffAlex 等人的作品……
                    • 脚本执行连同 ssh #!/usr/bin/expect set pass [lindex $argv 1] set host [lindex $argv 0] spawn ssh -t root@$host sh /tmp/anyscript .sh 期望 "*assword:" 发送 "$pass\n";互动”
                    【解决方案21】:

                    要通过 shell 脚本连接远程机器,请使用以下命令:

                    sshpass -p PASSWORD ssh -o StrictHostKeyChecking=no USERNAME@IPADDRESS
                    

                    其中IPADDRESSUSERNAMEPASSWORD 是需要在脚本中提供的输入值,或者如果我们想在运行时提供,请使用“读取”命令。

                    【讨论】:

                    • 这个答案在现有答案之上显示了什么? + 永远不要在不解释后果的情况下建议任何人使用StrictHostKeyChecking=no
                    【解决方案22】:

                    这在大多数情况下应该会有所帮助(您需要先安装 sshpass!):

                    #!/usr/bin/bash
                    read -p 'Enter Your Username: ' UserName;
                    read -p 'Enter Your Password: ' Password;
                    read -p 'Enter Your Domain Name: ' Domain;
                    
                    sshpass -p "$Password" ssh -o StrictHostKeyChecking=no $UserName@$Domain
                    

                    【讨论】:

                    • 这说明了什么其他现有答案还没有? + 切勿在未解释安全后果的情况下建议任何人使用 StrictHostKeyChecking=no
                    • 我在 OP 中没有看到任何 “又快又脏”
                    【解决方案23】:

                    在 linux/ubuntu 中

                    ssh username@server_ip_address -p port_number
                    

                    按回车键,然后输入您的服务器密码

                    如果您不是 root 用户,请在命令开头添加 sudo

                    【讨论】:

                      猜你喜欢
                      • 2017-07-05
                      • 2017-01-30
                      • 2021-12-14
                      • 2015-05-03
                      • 2015-11-03
                      • 2019-02-24
                      相关资源
                      最近更新 更多