如何使用 Bash 脚本中的密码运行 sftp 命令?
Posted
技术标签:
【中文标题】如何使用 Bash 脚本中的密码运行 sftp 命令?【英文标题】:How to run the sftp command with a password from Bash script? 【发布时间】:2011-07-20 04:17:46 【问题描述】:我需要使用sftp 从 Linux 主机将日志文件传输到远程主机。我的操作组为我提供了相同的凭据。但是,由于我无法控制其他主机,因此我无法生成并与其他主机共享 RSA 密钥。
那么有没有办法通过 cron 作业从 Bash 脚本内部运行 sftp
命令(使用提供的用户名/密码)?
我发现了一个类似的 Stack Overflow 问题,Specify password to sftp in a Bash script,但我的问题没有令人满意的答案。
【问题讨论】:
【参考方案1】:除了使用公钥身份验证之外,您还有其他几种选择:
-
使用keychain
使用sshpass(安全性较低,但可能满足您的要求)
使用expect(安全性最低,需要更多编码)
如果您决定给 sshpass 一个机会,这里有一个工作脚本 sn-p 可以这样做:
export SSHPASS=your-password-here
sshpass -e sftp -oBatchMode=no -b - sftp-user@remote-host << !
cd incoming
put your-log-file.log
bye
!
【讨论】:
在 Mac 上使用它:***.com/questions/9102557/… 我认为不需要导出。SSHPASS=password sshpass -e ...
应该这样做。
我能够做一个单行下载日志文件:sshpass -p "my_password" sftp -oPort=9999 user@host:dir/file.log
@gorus:单行非常酷,但我不想在命令行上使用密码,因为窥探风险增加。
-oBatchMode=no
对我来说是至关重要的缺失部分。【参考方案2】:
另一种方法是使用 lftp:
lftp sftp://user:password@host -e "put local-file.name; bye"
这种方法的缺点是计算机上的其他用户可以通过ps
等工具读取密码,并且密码可能成为您的shell 历史记录的一部分。
自 LFTP 4.5.0 以来可用的更安全的替代方法是设置 LFTP_PASSWORD
环境变量并使用 --env-password
执行 lftp。这是一个完整的例子:
export LFTP_PASSWORD="just_an_example"
lftp --env-password sftp://user@host -e "put local-file.name; bye"
# Destroy password after use
export LFTP_PASSWORD=""
LFTP 还包括一个很酷的镜像功能(可以包括确认传输后删除--Remove-source-files
):
lftp -e 'mirror -R /local/log/path/ /remote/path/' --env-password -u user sftp.foo.com
【讨论】:
+1 用于建议替代方案,但我们可以避免在命令行上提供密码吗? 拒绝向同一台计算机上的任何人显示密码 您可以为 lftp 创建脚本文件,这样您就不必在命令行中提供密码。创建一个文件put-script
:open sftp://user:password@host; put local-file.name; exit
,然后运行lftp -f put-script
这样您就不必在命令行中拥有用户名和密码,并且可以为您的脚本文件设置限制性权限。
lftp
比处理sftp
和sshpass
要容易得多。很好的答案。
@AaronDigulla 赞成,因为这正是 OP 所要求的——“一种运行 sftp 命令的方法(使用用户名/提供的密码 ) 从 Bash 脚本内部"。【参考方案3】:
EXPECT
是一个很棒的程序。
在 Ubuntu 上安装它:
sudo apt-get install expect
在 CentOS 机器上安装它:
yum install expect
假设您要连接到 sftp 服务器,然后将本地文件从本地计算机上传到远程 sftp 服务器
#!/usr/bin/expect
spawn sftp username@hostname.com
expect "password:"
send "yourpasswordhere\n"
expect "sftp>"
send "cd logdirectory\n"
expect "sftp>"
send "put /var/log/file.log\n"
expect "sftp>"
send "exit\n"
interact
这将使用您的密码打开到服务器的 sftp 连接。
然后它转到您要上传文件的目录,在本例中为“logdirectory”
这会从位于 /var/log/ 的本地目录中将文件名为 file.log 的日志文件上传到远程服务器上的“日志目录”
【讨论】:
感谢您的回答,我曾期望这是完成此任务的选择之一。 谢谢。我通过搜索找到了您的答案,使用它并使用期望成功构建了一个脚本。刚刚发布了poterity的脚本 非常感谢你的回答,我已经投票了:) 我正在使用它来输入 ssh 私钥的密码。将相同的公钥放在所有服务器上并定期轮换私钥密码短语会更方便。【参考方案4】:您可以在 shell 脚本中以交互方式使用 lftp,这样密码就不会保存在 .bash_history 或类似文件中,方法是:
vi test_script.sh
将以下内容添加到您的文件中:
#!/bin/sh
HOST=<yourhostname>
USER=<someusername>
PASSWD=<yourpasswd>
cd <base directory for your put file>
lftp<<END_SCRIPT
open sftp://$HOST
user $USER $PASSWD
put local-file.name
bye
END_SCRIPT
在您为您的 put 文件输入 :wq
编辑主机、用户、通行证和目录后写入/退出 vi 编辑器。然后使您的脚本可执行 chmod +x test_script.sh
并执行它 ./test_script.sh
。
【讨论】:
要覆盖现有文件,请在 lftp 之后添加“set xfer:clobber on” 【参考方案5】:您可以通过启用无密码身份验证来覆盖。但是你应该在开始之前安装密钥(pub,priv)。
在本地服务器上执行以下命令。
Local $> ssh-keygen -t rsa
对于所有提示选项,请按 ENTER。无需输入任何值。
Local $> cd .ssh
Local $> scp .ssh/id_rsa.pub user@targetmachine:
Prompts for pwd$> ENTERPASSWORD
使用以下命令连接到远程服务器
Local $> ssh user@targetmachine
Prompts for pwd$> ENTERPASSWORD
在远程服务器上执行以下命令
Remote $> mkdir .ssh
Remote $> chmod 700 .ssh
Remote $> cat id_rsa.pub >> .ssh/authorized_keys
Remote $> chmod 600 .ssh/authorized_keys
Remote $> exit
在本地服务器上执行以下命令以测试无密码身份验证。 应该是无密码连接的。
$> ssh user@targetmachine
【讨论】:
+1 为您的答案,但问题是关于在没有公钥/私钥的情况下进行操作。 哎呀.. 刚刚看到密钥共享的限制:) 出于好奇,当从 shell 脚本调用此命令lftp -p $port -u $login_id,$password $ip_number
时,会在哪里打印它们?除了 sshpass 你是怎么解决的?
我没有 lftp
并且依赖于来自 Mac 和 Linux 的 sshpass
。
纯金。谢谢! :)【参考方案6】:
最近有人要求我从 ftp 切换到 sftp,以确保服务器之间的文件传输安全。我们正在使用 Tectia SSH 包,它有一个选项 --password
在命令行上传递密码。
示例:sftp --password="password" "userid"@"servername"
批处理示例:
(
echo "
ascii
cd pub
lcd dir_name
put filename
close
quit
"
) | sftp --password="password" "userid"@"servername"
我想我应该分享这些信息,因为在运行帮助命令 (sftp -h
) 之前,我查看了各种网站,看到密码选项让我感到惊讶。
【讨论】:
+1 给你很好的建议。但是,这将要求您在命令行上传递密码,系统上执行ps
命令的任何人都可以看到您的密码。
我试过了,我得到了unknown option -- - usage: sftp [-1246aCfpqrv] [-B buffer_size] [-b batchfile] [-c cipher] [-D sftp_server_path] [-F ssh_config] [-i identity_file] [-l limit] [-o ssh_option] [-P port] [-R num_requests] [-S program] [-s subsystem | sftp_server] host sftp [user@]host[:file ...] sftp [user@]host[:dir[/]] sftp -b batchfile [user@]host
@ihue 可能是因为您需要 Techia SSH,而不是 OpenSSH【参考方案7】:
将 sshpass 与锁定的凭据文件结合起来,实际上,它与任何东西一样安全 - 如果您有 root 权限来读取凭据文件,那么无论如何,所有的赌注都没有了。
【讨论】:
【参考方案8】:Bash 程序等待 sftp 要求输入密码然后发送:
#!/bin/bash
expect -c "
spawn sftp username@your_host
expect \"Password\"
send \"your_password_here\r\"
interact "
您可能需要安装 expect,将“密码”的措辞更改为小写“p”以匹配您收到的提示。这里的问题是它在文件以及命令历史记录中以纯文本形式公开您的密码。这几乎违背了最初拥有密码的目的。
【讨论】:
+1 但我认为您清楚地说明了这种方法存在什么问题。【参考方案9】:您可以使用 sshpass。以下是步骤
-
为 Ubuntu 安装 sshpass -
sudo apt-get install sshpass
如果是第一次,请将远程 IP 添加到已知主机文件
对于 Ubuntu -> ssh 用户@IP -> 输入“是”
给它一个 scp 和 sshpass 的组合命令。
以下是远程 tomcat 的战争应对示例代码
sshpass -p '#Password_For_remote_machine' scp /home/ubuntu/latest_build/abc.war #user@#RemoteIP:/var/lib/tomcat7/webapps
【讨论】:
【参考方案10】:我发现完成此任务的最简单方法是使用 Expect、SSHPASS...等任何第三方库,无需安装任何第三方库>CURL 和 SFTP。这两个几乎在每台 Linux 机器上都有。
这是您在更改值后应该执行的命令。
curl -k "sftp://SERVER_IP:SERVER_PORT/FULL_PATH_OF_THE_FILE" --user "SERVER_USER:SERVER_PASSOWRD" -o "THE_NAME_OF_THE_FILE_AFTER_DOWNLOADING_IT"
示例:
curl -k "sftp://10.10.10.10:77/home/admin/test.txt" --user "admin:123456" -o "test.txt"
解释:
我们正在使用用户名 admin 和密码 123456 连接到服务器 10.10.10.10:77,以移动文件 /home/admin/test.txt 从该服务器到您当前用于执行上述命令的服务器。
【讨论】:
这不是相反的方向吗?当问题是从本地上传到远程时,这显示了如何将文件从远程服务器复制到本地。【参考方案11】:您可以使用带有 scp 和 os 库的 Python 脚本进行系统调用。
-
ssh-keygen -t rsa -b 2048(本地机器)
ssh-copy-id user@remote_server_address
创建一个 Python 脚本,如:
import os
cmd = 'scp user@remote_server_address:remote_file_path local_file_path'
os.system(cmd)
-
在 crontab 中创建规则以自动化您的脚本
完成
【讨论】:
问题是关于使用密码认证,而不是公钥认证。 是的,你是对的,但对于其他寻找解决问题的替代方案的人来说可能很有用。因为问题是相关的。以上是关于如何使用 Bash 脚本中的密码运行 sftp 命令?的主要内容,如果未能解决你的问题,请参考以下文章
如何实现shell脚本使用sftp的用户名密码自动登录,而不使用公钥
linux定时通过shell脚本利用sftp命令上传文件。需要手动输入密码,用openSSH-clients这个插件可以解决么