在Linux/Unix中使用带密码的shell脚本实现SFTP自动化

时间:2020-01-09 10:37:16  来源:igfitidea点击:

什么是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命令示例执行了密码,但没有传输任何文件。