在Linux/Unix中使用带密码的shell脚本实现SFTP自动化
什么是SFTP批处理文件,以及如何在批处理模式下使用带密码的shell脚本自动化SFTP?
SFTP中的批处理文件可以是包含一系列命令的计划文本格式文件。
SFTP按照从上到下的顺序读取这些命令
此批处理文件用于"自动执行SFTP文件传输",也可以与脚本结合传输文件,而无需任何提示
在sftp中使用"-b"提供批处理文件名和路径,并在脚本中对sftp文件传输使用批处理模式
批处理模式从输入批处理文件(而不是stdin)读取一系列命令。
由于批处理模式缺少交互,因此可以将批处理文件与SFTP shell脚本一起使用,而无需使用SFTP authorized\密钥提示密码
批处理文件还可以用于使用带密码的shell脚本自动化SFTP,但我们可能需要其他工具,如sshpass、expect等,以避免密码提示和用户交互
"
-
"的批处理文件可用于指示标准输入。如果以下任何命令失败,sftp将中止:get、put、reget、reput、rename、ln、rm、mkdir、chdir、ls、lchdir、chmod、chown、chgrp、lpwd、df、symlink和lmkdir。
通过在命令前面加上"-"字符(例如,
-rm/tmp/blah\*
),可以逐个命令地支持错误终止。
因此,通过上面的解释,我们知道使用批处理文件,我们可以为这两种情况使用脚本自动化SFTP文件传输
不提示密码的SFTP shell脚本,即无密码的SFTP(使用SFTP"authorized_keys")
带有密码的SFTP shell脚本(使用'expect'、'sshpass'或者类似工具传递密码)
无提示密码的SFTP shell脚本(无密码SFTP)
创建SFTP脚本来传输文件而不提示密码
我们可以按照我在脚本中添加的其他注释来理解整个功能。
[root@server1 ~]# cat /tmp/sftpsync.sh #!/bin/bash ## Description: # Get user, remote server, source directory with absolute path and # remote directory details as input to sync the latest added files # with remote server ## Use batch file with SFTP shell script without prompting password # using SFTP authorized_keys ################################################################### # Create SFTP batch file tempfile="/tmp/sftpsync.$$" count=0 trap "/bin/rm -f $tempfile" 0 1 15 if [ $# -eq 0 ] ; then echo "Usage:[root@server1 ~]# touch /src_dir/file{1..3}user host path_to_src_dir remote_dir" >&2 exit 1 fi # Collect User Input user="" server="" remote_dir="" source_dir="" timestamp="$source_dir/.timestamp" # Without source and remote dir, the script cannot be executed if [[ -z $remote_dir ]] || [[ -z $source_dir ]]; then echo "Provide source and remote directory both" exit 1 fi echo "cd $remote_dir" >> $tempfile # timestamp file will not be available when executed for the very first time if [ ! -f $timestamp ] ; then # no timestamp file, upload all files for filename in $source_dir/* do if [ -f "$filename" ] ; then # Place the command to upload files in sftp batch file echo "put -P \"$filename\"" >> $tempfile # Increase the count value for every file found count=$(( $count + 1 )) fi done else # If timestamp file found then it means it is not the first execution so look out for newer files only # Check for newer files based on the timestamp for filename in $(find $source_dir -newer $timestamp -type f -print) do # If found newer files place the command to upload these files in batch file echo "put -P \"$filename\"" >> $tempfile # Increase the count based on the new files count=$(( $count + 1 )) done fi # If no new files found the do nothing if [ $count -eq 0 ] ; then echo "[root@server1 ~]# /tmp/sftpsync.sh hynman server2 /src_dir dest_dir Synchronizing: Found 3 files in local folder to upload. sftp> cd dest_dir sftp> put -P "/src_dir/file3" sftp> put -P "/src_dir/file1" sftp> put -P "/src_dir/file2" sftp> quit Done. All files synchronized up with server2: No files require uploading to $server" >&2 exit 1 fi # Place the command to exit the sftp connection in batch file echo "quit" >> $tempfile echo "Synchronizing: Found $count files in local folder to upload." # Main command to use batch file with SFTP shell script without prompting password sftp -b $tempfile "$user@$server" echo "Done. All files synchronized up with $server" # Create timestamp file once first set of files are uploaded touch $timestamp # Remove the sftp batch file rm -f $tempfile exit 0
验证
现在,我们有了SFTP脚本,可以使用SFTP"authorized_keys"在不使用密码的情况下传输文件,现在是时候验证脚本功能了:
测试环境
SFTP客户端:
主机名:
server1. example.com
IP地址:
10.10.10.12
包含要传输的文件的源目录:
/src_dir
SFTP服务器:
主机名:
server2. example.com
IP地址:
10.10.10.13
包含要收集的文件的远程目录:
dest_dir
Chroot-Jail路径:
/opt/sftp-jails/hynman
我们将在"server1"的源目录下创建一些新文件`
[root@server1 ~]# /tmp/sftpsync.sh hynman server2 /src_dir dest_dir /tmp/sftpsync.sh: No files require uploading to server2
接下来使用sftp脚本将文件从"server1"传输到"server2"`
# touch /src_dir/file{4..5}
因此,所有的文件传输成功使用批处理文件与SFTP脚本没有提示密码。
接下来,如果我们尝试重新运行脚本,那么我们会看到,由于没有新的文件要传输,所以脚本不会执行任何操作。
# /tmp/sftpsync.sh hynman server2 /src_dir dest_dir Synchronizing: Found 2 files in local folder to upload. sftp> cd dest_dir sftp> put -P "/src_dir/file5" sftp> put -P "/src_dir/file4" sftp> quit Done. All files synchronized up with server2
因此,我们将在"server1"的源目录下创建更多的新文件`
[root@server1 ~]# yum -y install expect
接下来重新运行sftp脚本来传输文件。
user_pwd=""
正如预期的那样,新文件被自动识别并使用带有SFTP脚本的批处理文件传输,而无需提示密码。
使用带密码的shell脚本(使用Expect)自动化SFTP
现在,我们可以使用带有密码的shell脚本以及多个第三方工具(如"expect"或者"sshpass")来自动化SFTP。在我们的示例中,我将展示unixshell脚本中的SFTP命令示例,其中密码使用expect
在客户端节点上安装Expect
假设我们已经配置了一个SFTP服务器,第一步是在客户机节点上安装expect(对我们来说是"server1")。
默认情况下,并非所有Linux和Unix变体上都安装了"expect"。因为我使用的是RHEL/CentOS 7/8变体,所以我将使用yum/dnf安装expect
expect -c " spawn sftp -o "BatchMode=no" -b "$tempfile" "$user@$server" expect -nocase \"*password:\" { send \"your_password\r\"; interact } "
unixshell脚本中带密码的SFTP命令示例
接下来我们将"创建一个与bash结合的脚本,并期望使用带有密码的shell脚本自动化SFTP"。
提示:
在下面的脚本中,我们将在sftp shell脚本中以纯文本格式提供sftp用户的密码,为了避免这种情况,我们还可以通过添加另一个变量来收集此密码作为输入,例如:
[root@server1 ~]# cat /tmp/sftpsync.sh #!/bin/bash ## Description: # Get user, remote server, source directory with absolute path and # remote directory details as input to sync the latest added files # with remote server ## Execute SFTP command example in Unix shell script with password # Using batch file with expect ################################################################## tempfile="/tmp/sftpsync.$$" count=0 <Output trimmed> if [ $count -eq 0 ] ; then echo "[root@server1 ~]# touch /src_dir/file{6..7}: No files require uploading to $server" >&2 exit 1 fi echo "quit" >> $tempfile expect -c " spawn sftp -o "BatchMode=no" -b "$tempfile" "$user@$server" expect -nocase \"*password:\" { send \"My_Passw0rd\r\"; interact } " echo "Synchronizing: Found $count files in local folder to upload." touch $timestamp rm -f $tempfile exit 0
因此,用户必须传递用户的密码作为最后一个输入参数。还可以增强脚本以传递加密的密码,然后在脚本中对其进行解密以提高安全性。
下面是使用密码在Unix shell脚本中执行SFTP命令的示例expect脚本:
[root@server1 ~]# /tmp/sftpsync.sh hynman server2 /src_dir dest_dir spawn sftp -o BatchMode=no -b /tmp/sftpsync.13391 hynman@server2 hynman@server2's password: sftp> cd dest_dir sftp> put -P "/src_dir/file6" sftp> put -P "/src_dir/file7" sftp> quit Synchronizing: Found 2 files in local folder to upload. Done. All files synchronized up with server2
我们可以将这个expect脚本放在现有的/tmp中/同步.sh我们之前创造的
[root@server1 ~]# /tmp/sftpsync.sh hynman server2 /src_dir dest_dir /tmp/sftpsync.sh: No files require uploading to server2
验证
现在,由于我们在Unix shell脚本中有了SFTP命令示例,其中密码使用expect和批处理文件,现在是时候验证脚本功能了:
我的实验室环境
SFTP客户端:
主机名:
server1. example.com
IP地址:
10.10.10.12
包含要传输的文件的源目录:
/src_dir
SFTP服务器:
主机名:
server2. example.com
IP地址:
10.10.10.13
包含要收集的文件的远程目录:
dest_dir
Chroot-Jail路径:
/opt/sftp-jails/hynman
我们将在"server1"的源目录下创建一些新文件`
##代码##接下来,执行脚本以验证Automatic SFTP using shell script with password是否正常工作:
##代码##正如预期的那样,新文件被传输到"server2"的目标目录。因此,我们在unixshell脚本中使用expect和批处理文件的SFTP命令示例可以正常工作。
如果重新运行脚本而不添加新文件:
##代码##由于我们的源目录中没有新文件,所以在unixshell脚本中的SFTP命令示例执行了密码,但没有传输任何文件。