使用SSHpass实现远程服务器免密登陆和文件传输
使用SSHpass实现远程服务器免密登陆和文件传输

使用SSHpass实现远程服务器免密登陆和文件传输

使用SSHpass实现远程服务器免密登陆和文件传输
Password-free Login and File Transferring with Remote Server using SSHpass

Jiawei Xu
Released: 2022-10-07 / Updated: 2022-10-31

日常工作中免不了需要登陆远程服务器,并下载或上传文件。常规的做法是安装XShell,WinSCP,FileZilla等客户端软件,借助图形化界面进行文件操作,也可以用命令行开展工作。以上软件均可看作是对Windows/Linux系统自带的ssh/scp指令的一种封装与图形化表示,在日常工作中,用好ssh/scp指令也是很方便的。使用这两条指令的缺点是:1). 每次都需要输入用户名和主机地址;2). 每次都需要输入密码。对于第一个问题,一般可以通过设置别名(如Linux的alias)来解决,但输入密码仍然无法回避。这里介绍使用SSHpass解决ssh/scp命令密码验证的方法。

1. Linux安装SSHpass

对于有root权限的情况:

yum install -y epel-release
yum repolist
yum install -y sshpass

对于无root权限的情况,从源码进行安装,假定解压后的目录是/home/jwxu/sshpass-1.08:

wget http://sourceforge.net/projects/sshpass/files/sshpass/1.05/sshpass-1.08.tar.gz
tar -xvzf sshpass-1.08.tar.gz
cd /home/jwxu/sshpass-1.08
mkdir bin
./configure --prefix=/home/jwxu/sshpass-1.08/bin
make && make install -j

在.bashrc中添加以下环境变量并source ~/.bashrc:

export PATH=$PATH:/home/jwxu/sshpass-1.08/sshpass

运行SSHpass:

sshpass -p password ssh [-p port] username@host
sshpass -p password scp [-P port] [-r show progress] username@host:~/file.tar ./

2. 命令设置

准备以下脚本,例如命名为xconnect:

#!/usr/bin/python3

import os,sys

name_list=['aaa','bbb','ccc']
host_list=['a@ipa','b@ipb','c@ipc']
passwd_list=['passwordforaaa','passwordforbbb','passwordforccc']
port_list=[portforaaa,portforbbb,portforccc] # Usually default port number is 22

def getpasswd(name):
	num=0
	host,passwd,port='','',''
	for i in range(len(name_list)):
		num+=1
		if name==name_list[i]:
			host=host_list[i]
			passwd=passwd_list[i]
			port=port_list[i]
	if host=='':
		return False
	else:
		return True,host,passwd,port

command,name=sys.argv[1],sys.argv[2]
check,host,passwd,port=False,'','',22

if len(getpasswd(name))==1:
	print('Not in host list!')
else:
	check,host,passwd,port=getpasswd(name)

if command=='ssh':
	ssh_command='sshpass -p "'+passwd+'" ssh -p '+str(port)+' '+host
	print(ssh_command+'\n')
	os.system(ssh_command)
elif command=='scpdown' or command=='scpup':
	localdir=sys.argv[3]
	clouddir=sys.argv[4]
	if command=='scpdown':
		scp_command='sshpass -p "'+passwd+'" scp -P '+str(port)+' -r '+host+':~'+clouddir+' '+localdir
		print(scp_command+'\n')
		os.system(scp_command)
	elif command=='scpup':
		scp_command='sshpass -p "'+passwd+'" scp -P '+str(port)+' -r '+localdir+' '+host+':~'+clouddir
		print(scp_command+'\n')
		os.system(scp_command)

修改line 5~8的账户信息,其中line 5为账户别名,用于登陆时使用。使用方法如下:

# xconnect operation hostname [local file or route] [remote file or route]
# For examples,
# Connect to remote server named 'kalinite':
>> xconnect ssh kalinite
# Download file from remote server to current directory:
>> xconnect scpdown kalinite . /data/output.tar # Note: '/data/output.tar' stands for '~/data/output.tar' so that you don't need to type '~'
# Upload file to remote server:
>> xconnect scpup kalinite ./input.tar /kalinite/workdir/

默认在运行相应指令是输出实际运行的SSHpass命令,可以注释脚本中的两行print使其不输出。

下面是一些实用的例子:

alias upall='for i in ./*.*;do xconnect scpup host $i /dir;done'
alias tarallup='tar -cf up.tar;xconnect scpup host up.tar /dir;rm -f up.tar' # Especially useful for a lot of small files
alias uplogin='tar -cf up.tar;xconnect scpup host up.tar /dir;rm -f up.tar;xconnet ssh host'

需要注意的是,xconnect脚本中已经包含了账户密码等信息,存在一定风险。可行的办法是将xconnect打包编译成二进制可执行文件。首先安装PyInstaller扩展包,然后将xconnect打包,在产生的dist文件夹下有打包完的二进制可执行文件,较源代码安全性有所提高。

>> pip install pyinstaller
# Or mirror package: pip install -i [mirror] pyinstaller
>> pyinstaller -F xconnect
>> cd dist