ssh登录最基本用法
# 假定你要以用户名user,登录远程主机host
ssh user@host
# 如果本地用户名与远程用户名一致,可以省去用户名
ssh host
# SSH的默认端口是22,也就是说,你的登录请求会送进远程主机的22端口。使用p参数,可以修改这个端口。
ssh -p 8081 user@host
第一次登录对方主机,系统会提示信息,让你确认host主机的真实性,然后要求输入密码,当远程主机的公钥被接受以后,它就会被保存在文件$HOME/.ssh/known_hosts
之中,下次再连接这台主机,系统就会认出它的公钥已经保存在本地了,从而跳过警告部分,直接提示输入密码。
每个SSH
用户都有自己的known_hosts
文件,此外系统也有一个这样的文件,通常是/etc/ssh/ssh_known_hosts
,保存一些对所有用户都可信赖的远程主机的公钥。
公钥登录(免密登录)
- 使用密码登录,每次都必须输入密码,非常麻烦。好在SSH还提供了公钥登录,可以省去输入密码的步骤。
- 所谓"公钥登录",原理很简单,就是用户将自己的公钥储存在远程主机上。登录的时候,远程主机会向用户发送一段随机字符串,用户用自己的私钥加密后,再发回来。远程主机用事先储存的公钥进行解密,如果成功,就证明用户是可信的,直接允许登录shell,不再要求密码。
- 这种方法要求用户必须提供自己的公钥。如果没有现成的,可以直接用ssh-keygen生成一个
# 系统会出现一系列提示,可以一路回车。其中有一个问题是,要不要对私钥设置口令(passphrase),如果担心私钥的安全,这里可以设置一个。
# 运行结束以后,在$HOME/.ssh/目录下,会新生成两个文件:id_rsa.pub和id_rsa。前者是你的公钥,后者是你的私钥。
ssh-keygen -t rsa -C 350442340@qq.com
- 将公钥传送到远程主机host上面
ssh-copy-id user@host
解释ssh-copy-id
原理,公钥保存过程
远程主机将用户的公钥,保存在登录后的用户主目录的$HOME/.ssh/authorized_keys文件中。公钥就是一段字符串,只要把它追加在authorized_keys文件的末尾就行了。
这里不使用ssh-copy-id
ssh user@host 'mkdir -p .ssh && cat >> .ssh/authorized_keys' < ~/.ssh/id_rsa.pub
依次分解开来看:
$ ssh user@host
表示登录远程主机;mkdir .ssh && cat >> .ssh/authorized_keys
,表示登录后在远程shell上执行的命令:$ mkdir -p .ssh
的作用是,如果用户主目录中的.ssh目录不存在,就创建一个;'cat >> .ssh/authorized_keys' < ~/.ssh/id_rsa.pub
的作用是,将本地的公钥文件~/.ssh/id_rsa.pub
,重定向追加到远程文件authorized_keys
的末尾。- 写入authorized_keys文件后,公钥登录的设置就完成了。
SFTP,使用Transmit
客户端,添加服务器,左右拖动即可
brew search transmit
brew install transmit
brew info transmit
SFTP命令
# 连接远程linux,输入密码即可
sftp user@host
# 查看远程当前工作路径
pwd
cd ../
# 查看本地当前工作路径 location
lpwd
lcd ../
# 上传文件
put -r [本地路径] [远程路径]
# 上传文件夹(在远程新建文件夹)
put -r [本地路径/文件夹/*] [远程路径/新建文件夹/]
# 下载文件
get -r [远程路径] [本地路径]
# 下载文件夹(在本地新建文件夹)
get -r [远程路径/文件夹/*] [本地路径/新建文件夹/]
# 退出
exit
scp使用
# 远程拷贝到本地
scp -r user@host:[远程路径] [本地路径]
# 本地拷贝到远程
scp -r [本地路径] user@host:[远程路径]
sftp和scp。2者的最大不同之处在于「SFTP在文件传输过程中中断的话,连接后还可以继续传输,但SCP不行」。
scp相对轻量一点
变量
- 常用系统变量
$HOME
$PWD
$SHELL
$USER
- 自定义变量: 变量=值 。中间不能有空格
A=2
echo $A
# 撤销变量
unset A
- 变量默认类型都是字符串类型,无法直接进行数值运算
- 如果有空格,需要用双引号或单引号括起来
- 可以把变量提升为全局变量,可供其他Shell程序使用
A=hahaha
export A
特殊变量:
$n
, n为数字,$0代表脚本名称, $1-$9 代表第一个到第九个参数$#
, 获取所有输入参数个数,常用于循环$*
, 代表命令行中所有的参数,把所有参数看成一个整体$@
, 代表命令行中所有的参数,把每个参数区分对待$?
, 最后一次执行的命令的返回状态。=0表示正确执行,非0表示执行错误
运算符
$((表达式))
或$[表达式]
expr +,-,\*,/,%
加减乘除,取模. expr运算符间要有空格
expr `expr 2 + 3` \* 4
result=$[(2+3)*4]
条件判断
[ condition ]
, condition前后必需要有空格,条件非空就为true.[]
返回false- 常用的判断条件
- 整数之间的比较
=
字符串比较-lt
小于(less than)-le
小于(less equal)-eq
小于(equal)-gt
小于(greater than)-ge
小于(greater equal)-ne
小于(not equal)
- 按文件权限进行判断
-r
有读的权限(read)-w
有写的权限(write)-x
有执行的权限(execute)
- 按文件类型进行判断
-f
文件存在并且是一个常规的文件(file)-e
文件存在(existence)-d
文件存在,并且是一个目录(directory)
[ 23 -ge 22 ]
流程控制
if [ 条件判断式 ]; then
coding
fi
# 或者
if [ 条件判断式 ]
then
coding
fi
注意事项:
- 条件判断式和中括号之间必需有空格
- if 后要有空格
case语句
case $var in
"value1")
coding
;;
"value2")
coding
;;
# 结尾相当于 default, 双分号相当于 break
*)
;;
esac
# case 倒过来写,表示结束
for 循环
echo "===== for循环方式1"
s=0
for ((i=1;i<=100;i++))
do
s=$[$s + $i]
done
echo "for循环方式1 is $s"
# 第二种方式
echo "===== for循环方式2"
s2=0
for i in $*
do
s2=$[ $s2 + $i ]
done
echo "for循环方式2 is $s2"
switch语句
case 值 in
模式1)
command
;;
模式2)
command
;;
*)
command
;;
esac
取值后面必须为关键字 in,每一模式必须以右括号结束。取值可以为变量或常数。匹配发现取值符合某一模式后,其间所有命令开始执行直至 ;;。;; 与其他语言中的 break 类似,意思是跳到整个 case 语句的最后。
取值将检测匹配的每一个模式。一旦模式匹配,则执行完匹配模式相应命令后不再继续其他模式。如果无一匹配模式,使用星号 * 捕获该值,再执行后面的命令。
函数
function function_name () {
list of commands
echo "$1 $2 $* $@ [$#]个数"
[ return value ]
}
function_name 3 9
function
可以不写,函数返回值,可以显式增加 return 语句;如果不加,会将最后一条命令运行结果作为返回值。函数返回值只能是整数
字符串
字符串是 shell 编程中最常用最有用的数据类型(除了数字和字符串,也没啥其它类型好用了),字符串可以用单引号,也可以用双引号,也可以不用引号。单双引号的区别跟 PHP 类似。
- 单引号: 单引号里的任何字符都会原样输出,单引号字符串中的变量是无效的; 单引号字串中不能出现单引号(对单引号使用转义符后也不行)
- 双引号:双引号的优点: 双引号里可以有变量 双引号里可以出现转义字符
# 拼接字符串
your_name="qinjx"
greeting="hello, "$your_name" !"
greeting_1="hello, ${your_name} !"
echo $greeting $greeting_1
# 获取字符串长度
string="alibaba is a great company"
echo ${#string}
# 提取子字符串
echo ${string:1:4} #输出 liba
# 查找子字符串
echo `expr index "$string" is`
数组
bash 支持一维数组(不支持多维数组),并且没有限定数组的大小。类似与 C 语言,数组元素的下标由0开始编号。获取数组中的元素要利用下标,下标可以是整数或算术表达式,其值应大于或等于0。
在 Shell 中,用括号来表示数组,数组元素用“空格”符号分割开。定义数组的一般形式为:
array_name=(value1 ... valuen)
# 还可以单独定义数组的各个分量: 可以不使用连续的下标,而且下标的范围没有限制。
array_name[0]=value0
array_name[1]=value1
array_name[2]=value2
# 读取数组元素值的一般格式是:
valuen=${array_name[2]}
# 使用@或*可以获取数组中的所有元素,例如:
${array_name[*]}
${array_name[@]}
# 获取数组长度的方法与获取字符串长度的方法相同
# 取得数组元素的个数
length=${#array_name[@]}
# 或者
length=${#array_name[*]}
# 取得数组单个元素的长度
lengthn=${#array_name[n]}
awk
- 读(Read),AWK 从输入流(文件、管道或者标准输入)中读入一行然后将其存入内存中。
- 执行(Execute), 对于每一行输入,所有的 AWK 命令按顺执行。 默认情况下,AWK 命令是针对于每一行输入,但是我们可以将其限制在指定的模式中。
- 重复(Repeate),一直重复上述两个过程直到文件结束。
- 程序的结构
BEGIN {awk-commands} # 开始块 可选, 在整个过程中只执行一次
/pattern/ {awk-commands} # 主体块
END {awk-commands} # 结束块 可选, 在整个过程中只执行一次
awk基本语法
awk [options] file ...
# 从文件中读取awk指令
awk -f command.awk marks.txt
AWK 标准选项
-v
选项,可以为变量赋值。它允许在程序执行之前为变量赋值。
awk -v name=Jerry 'BEGIN{printf "Name = %s\n", name}' # Name = Jerry