我难免会用别人的电脑连接远程服务器,每到这时传文件都显得非常麻烦。一般也不去另外装东西,就用scp命令传文件,每次都要把服务器、用户名、配置的内容打进去。传一次,打一次,手残打错或者上翻命令的时候,真是格外崩溃。最理想的状态,传文件也可以有一个简单的方法,放在点文件里面。这篇文章就是这个配置,通过点文件让scp文件上传下载简化成 scp pull local_file remote_file。

本文主要记录了放进点文件的代码的内容,附带的把设置ssh密钥对也放在文章后面。如果熟悉这些内容,可供复制的代码直接在效果展示一节。

效果展示

文章开始,照例展示一下成品,将本文的代码放到点文件(.bashrc)里之后,就可以通过自定义的scpp命令完成文件的上传下载,看上去会是这样的:

1
2
scpp push -r local_folder ./
scpp pull remote_file local_file

为了方便直接取用,如果不想看具体的文章,将下面这行代码添加到点文件当中,更改用户名、地址、配置即可:

1
scpp(){(read U S P<<<'user ip ~/tmp/';O='-P 22';H='usage:   scpp [push|pull] [scp options] source target';if [ $1 != 'push' ]&&[ $1 != 'pull' ]||[ $# -lt 3 ];then echo $H;return 2;fi;[ $1 = 'push' ]&&scp ${@:2:$#-3} $O ${@:(-2):1} $U@$S:$P${!#};[ $1 = 'pull' ]&&scp ${@:2:$#-3} $O $U@$S:$D${@:(-2):1} ${!#})}

简化scp命令

scp命令和ssh一起都会装好,但是使用的时候看上去都是这样的:

1
2
scp -P 22 package.tar.gz username@server_ip:~/tmp/package
scp -P 22 -r username@server_ip:~/tmp/logfile logfile

每次上传下载都会需要把配置和用户名、地址完整打一遍,即使上翻命令然后改也非常不方便。

其实重复的内容有三个,用户名、地址、配置,有时候我会把他们添加到环境变量里,于是就变成:

1
2
scp $OPTIONS package.tar.gz $USERNAME@$SERVER:$DEFAULT_PATH/package
scp $OPTIONS -r $USERNAME@$SERVER:$DEFAULT_PATH/logfile logfile

虽然不会省很多事儿,但起码不会输错了,如果变量名无所谓阅读的话还是能省不少事儿的。

为了进一步简化,就干脆写了个函数:

1
2
3
4
5
6
7
8
9
10
11
function scpp () {
local USERNAME='username'
local SERVER='server_ip'
local OPTIONS='-P 22'
local DEFAULT_PATH='~/tmp/'
local USAGE="usage: scpp [push|pull] [scp options] source target"

if [ $1 != 'push' ] && [ $1 != 'pull' ] || [ $# -lt 3 ]; then echo $USAGE; return 2; fi
[ $1 = 'push' ] && scp ${@:2:$#-3} $OPTIONS ${@:(-2):1} $USERNAME@$SERVER:$DEFAULT_PATH${!#}
[ $1 = 'pull' ] && scp ${@:2:$#-3} $OPTIONS $USERNAME@$SERVER:$DEFAULT_PATH${@:(-2):1} ${!#}
}

将这个函数放进点文件(.bashrc),重新加载即可。

当然,需要把用户名、地址、常规配置、默认远端文件夹改成你需要的内容。

1
source .bashrc

加载了这个函数后,上传下载就简化成这样了:

1
2
scpp push package.tar.gz ./
scpp pull -r logfile logfile

当然根据需要,完全可以再更改完配置后把代码简化成一行,点文件加一行代码就可以达到这个效果。

设置密钥对

经常忘记免密码登录需要设置的那个密钥对,这里顺带也做一个记录。

1
2
3
cd ~/.ssh
ssh-keygen -t rsa -C "geoff@home" -N "" -f id_rsa
cat ~/.ssh/id_rsa.pub | ssh username@server 'cat >> ~/.ssh/authorized_keys'

简单的来说就是创建密钥对然后放进去,如果还是不行,检查一下文件权限和ssh设置。

1
2
cat /etc/ssh/sshd_config | grep RSAAuthentication
cat /etc/ssh/sshd_config | grep PubkeyAuthentication

scp和ssh就是类似的东西,免密码登录不需要额外的设置。

为scpp设置自动补全

最简单的方式,可以使用complete命令添加自动补全。
先提供完整的补全命令,放在.bashrc中即可:

1
_scpp(){ [[ ${#COMP_WORDS[*]} -le 2 ]]&&COMPREPLY=($(compgen -W 'pull push' ${COMP_WORDS[1]}))||COMPREPLY=($(compgen -A file)); };complete -F _scpp scpp

下面分解来解释一下命令里有些什么。
通过如下命令让_scpp函数处理scpp的自动补全:

1
complete -F _scpp scpp

处理函数中常用的变量有这些:

variable description
COMP_WORDS 类型为数组,存放当前命令行中输入的所有单词
COMP_CWORD 类型为整数,当前输入的单词在COMP_WORDS中的索引
COMPREPLY 类型为数组,候选的补全结果
COMP_WORDBREAKS 类型为字符串,表示单词之间的分隔符
COMP_LINE 类型为字符串,表示当前的命令行输入字符
COMP_POINT 类型为整数,表示光标在当前命令行的哪个位置

函数最后设置的COMPREPLY数组会通过<TAB>完成补全。
更具体的补全就是简单的文档内容,可以在这里扩展阅读。