sshpass使用详解

sshpass主要的作用是可以在命令行直接使用密码来进行远程操作(远程连接和远程拉取文件)或是免密免交互进行某些本地操作,之所以会聊到这个命令,今天在迁移发布打包脚本的时候整理查资料总结的

使用前提,需要安装sshpass:

//yum安装
yum -y install sshpass

//源码安装
tar xvzf sshpass-1.05.tar.gz 
cd sshpass-1.05.tar.gz 
./configure 
make 
make install 

实例1:

sshpass -p 密码 ssh -oStrictHostKeyChecking=no -p 端口 root@ip

如果不加-oStrictHostKeyChecking=no,是无法远程登录的.

StrictHostKeyChecking: 主机公钥确认
(1)StrictHostKeyChecking=no 最不安全的级别,当然也没有那么多烦人的提示了,相对安全的内网测试时建议使用。如果连接server的key在本地不存在,那么就自动添加到文件中(默认是known_hosts),并且给出一个警告。
(2)StrictHostKeyChecking=ask 默认的级别,就是出现刚才的提示了。如果连接和key不匹配,给出提示,并拒绝登录。
(3)StrictHostKeyChecking=yes 最安全的级别,如果连接与key不匹配,就拒绝连接,不会提示详细信息。

实例1:可以这样测试没有StrictHostKeyCheck为什么不行:

ssh p 端口 root@ip

会发现,原来需要登录确认,所以实例1指令如果后面的命令不带-oStrictHostKeyChecking就没反应:

[root@xxxxx ~]# ssh -p 端口 root@ip
The authenticity of host '[ip]:端口 ([ip]:端口)' can't be established.
ECDSA key fingerprint is cc:d8:89:91:b2:b9:56:4d:0b:d7:e3:c7:be:a4:c1:50.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '[ip]:端口' (ECDSA) to the list of known hosts.
root@ip's password:

当输入密码后,会往~/.ssh/know_hosts里加一条记录(表示信任),后续则不再需要check了.

除了上述ssh -o加上StrictHostKeyChecking=no之外,还可以用下面的方法免交互确认

~/.ssh/config (或者在/etc/ssh/ssh_config)
Host *(或是指定的host)
  StrictHostKeyChecking no

               

实例2:在本地执行远程机器的命令

sshpass -p xxx ssh root@192.168.11.11 "ethtool eth0"

[root@xxxx ~]# sshpass -p 密码 ssh -oStrictHostKeyChecking=no -p 端口号 root@ip
Last login: Thu May 28 23:50:49 2020 from ip2
Welcome to tlinux 2.2 64bit
[root@yy ~]# cd /tmp/
[root@yyy /tmp]# ls -lh | grep clark
-rw-r--r-- 1 root        root           0 May 28 23:51 clarksss.log

                   

实例3:从密码文件读取内容作为密码去远程连接主机

sshpass -f xxx.txt  ssh root@192.168.11.11

shell 脚本getopts用法总结

最近在写一个消费者的发布脚本,用到getopts,所以总结下getopts的用法

getopts是shell命令行参数解析工具,意在从shell 命令行当中解析参数。命令格式:

getopts optstring name [arg ...]

optstring列出了对应的shell 脚本可以识别的所有参数。比如:shell script可以识别-a, -f 以及-s参数,则optstring就是afs;如果对应的参数后面还跟随一个值,则在相应的optstring后面加冒号比如a:fs表示a参数后面会有一个值出现,-a value的形式另外,getopts执行匹配到a的时候,会把value存放在一个OPTARG的shell 变量中。如果optstring是以冒号开头的,命令行当中出现了optstring当中没有的参数将不会提示错误信息。

name表示的是参数的名称,每次执行getopts,会从命令行当中获取下一个参数,然后存放到name中。如果获取到参数不在optstring中,则name的值被设置为?。命令行当中的所有参数都有一个index,第一个参数从1开始,依次类推,另外有一个名为OPTIND的shell变量存放下一个要处理的参数的index。

直接上例子:

#!/bin/bash
 
func() {
    echo "Usage:"
    echo "test.sh [-j S_DIR] [-m D_DIR]"
    echo "Description:"
    echo "S_DIR,the path of source."
    echo "D_DIR,the path of destination."
    exit -1
}
 
upload="false"
 
while getopts 'h:j:m:u' OPT; do
    case $OPT in
        j) S_DIR="$OPTARG";;
        m) D_DIR="$OPTARG";;
        u) upload="true";;
        h) func;;
        ?) func;;
    esac
done
 
echo $S_DIR
echo $D_DIR
echo $upload

//执行结果:
[root@bobo tmp] sh test.sh -j /data/usw/web -m /opt/data/web
/data/usw/web
/opt/data/web
false
 
[root@bobo tmp] sh test.sh -j /data/usw/web -m /opt/data/web -u
/data/usw/web
/opt/data/web
true
 
[root@bobo tmp] sh test.sh -j /data/usw/web
/data/usw/web
 
false
 
[root@bobo tmp] sh test.sh -m /opt/data/web                 
 
/opt/data/web
false
 
[root@bobo tmp] sh test.sh -h
test.sh: option requires an argument -- h
Usage:
test.sh [-j S_DIR] [-m D_DIR]
Description:
S_DIR,the path of source.
D_DIR,the path of destination.
 
[root@bobo tmp] sh test.sh j
 
 
false
 
[root@bobo tmp] sh test.sh j m
 
 
false

getopts后面跟的字符串就是参数列表,每个字母代表一个选项,如果字母后面跟一个冒号,则表示这个选项还会有一个值,比如-j /data/usr/web 和 -m /opt/data/web。而getopts字符串中没有跟随冒号的字母就是开关型的选项,不需要指定值,等同于true/false,只要带上这个参数就是true。

shift位移使用举例:

#!/bin/bash
#test3.sh

func() {
        echo "Usage:"
        echo "test.sh [-j S_DIR] [-m D_DIR]"
        echo "Description:"
        echo "S_DIR, the path of source."
        echo "D_DIR, the path of destination."
        exit -1
}

upload="false"

echo $OPTIND

while getopts 'h:s:d:u' OPT; do
        case $OPT in
                s) S_DIR="$OPTARG";;
                d) D_DIR="$OPTARG";;
                u) upload="true";;
                h) func;;
                ?) func;;
        esac
done

echo $OPTIND
echo $(($OPTIND -))
echo $1

//执行结果:
[root@bobo tmp] sh test3.sh -s /data/usw/web beijing
1              #执行的是第一个"echo $OPTIND"
3              #执行的是第二个"echo $OPTIND"
beijing        #此时$1是"beijing"
 
[root@bobo tmp] sh test3.sh -s /opt/data/web beijing                
1              #执行的是第一个"echo $OPTIND"
3              #执行的是第二个"echo $OPTIND"
beijing
 
[root@bobo tmp] sh test3.sh -s /data/usw/web -d /opt/data/web beijing
1              #执行的是第一个"echo $OPTIND"
5              #执行的是第二个"echo $OPTIND"
beijing
 
                  参数位置: 1        2       3       4        5     6
[root@bobo tmp] sh test3.sh -s /data/usw/web -d /opt/data/web -u beijing
6
beijing

shell读取yaml文件

接上一篇spyc class for php 读取yaml配置文件之后,在构建脚本(shell编写的),也同样需要读取yaml config文件,于是上网找了下如何实现,文章来源于:
https://majing.io/posts/10000019511198

#!/bin/bash
function parse_yaml() {
    local yaml_file=$1
    local prefix=$2
    local s
    local w
    local fs
    s='[[:space:]]*'
    w='[a-zA-Z0-9_.-]*'
    fs="$(echo @|tr @ '\034')"
    (
        sed -ne '/^--/s|--||g; s|\"|\\\"|g; s/\s*$//g;' \
            -e "/#.*[\"\']/!s| #.*||g; /^#/s|#.*||g;" \
            -e  "s|^\($s\)\($w\)$s:$s\"\(.*\)\"$s\$|\1$fs\2$fs\3|p" \
            -e "s|^\($s\)\($w\)$s[:-]$s\(.*\)$s\$|\1$fs\2$fs\3|p" |
        awk -F"$fs" '{
            indent = length($1)/2;
            if (length($2) == 0) { conj[indent]="+";} else {conj[indent]="";}
            vname[indent] = $2;
            for (i in vname) {if (i > indent) {delete vname[i]}}
                if (length($3) > 0) {
                    vn=""; for (i=0; i<indent; i++) {vn=(vn)(vname[i])("_")}
                    printf("%s%s%s%s=(\"%s\")\n", "'"$prefix"'",vn, $2, conj[indent-1],$3);
                }
            }' |
        sed -e 's/_=/+=/g' \
            -e '/\..*=/s|\.|_|' \
            -e '/\-.*=/s|\-|_|'
    ) < "$yaml_file"
}
function create_variables() {
    local yaml_file="$1"
    eval "$(parse_yaml "$yaml_file")"
}

脚本提供了两个函数:

  • parse_yaml:读取yaml文件并直接输出结果。
  • create_variables:读取yaml文件,基于yaml文件的内容创建变量。

调用示例:

create_variables config.yml

linux top命令详解

top命令的第一行:

top – 21:31:26 up 15:16, 5 users, load average: 0.61, 0.82, 0.75
依次对应:系统当前时间 up 系统到目前为止运行的时间, 当前登录系统的用户数量,load_average后面的三个数字分别是距离现在一分钟,五分钟,十五分钟的负载情况。这一行的结果与uptime显示信息相同
load average 数据是每隔5s 检查一次活跃的进程数,然后特定算法计算出的数值。如果这个数除以逻辑cpu的数量,结果高于5的时候就表明系统在超负荷运转了。

top 命令的第二行:
Tasks: 240 total,   2 running,  238 sleeping,  0 stopped,  0  zombie依次对应:tasks表示任务(进程),240 total则表示现在有240个进程,其中处于运行中的有2个,238个在休眠(挂起),stopped 状态即停止的进程数为0, zombie状态即僵尸进程数为0

top命令第三行: cpu状态:%Cpu(s): 13.7 us, 1.5 sy, 0.0 ni, 84.2 id, 0.6 wa, 0.0 hi, 0.0 si, 0.0 st
us:user 用户空间占用cpu的百分比sy:system 内核空间占用cpu的百分比ni:niced 改变过优先级的进程占用cpu的百分比空闲cpu百分比wa: IO wait IO等待占用cpu的百分比hi: Hardware IRQ硬中断 占用cpu的百分比si: software软中断 占用cpu的百分比st: 被hypervisor偷去的时间

top命令第四行:内存状态:KB
KiB Mem : 3775264 total, 250100 free, 2495300 used, 1029864 buff/cache

依次对应:物理内存总量(3.7G),空闲内存总量(2.5G),使用中的内存总量(2.4G),缓冲内存量
第四行中使用中的内存总量(used)指的是现在系统内核控制的内存数,空闲内存总量(free)是内核还未纳入其管控范围的数量。纳入内核管理的内存不见得都在使用中,还包括过去使用过的现在可以被重复利用的内存,内核并不把这些可被重新使用的内存交还到free中去,因此在linux上free内存会越来越少,但不用为此担心

对于内存监控,在top里我们要时刻监控第五行swap交换分区的used,如果这个数值在不断的变化,说明内核在不断进行内存和swap的数据交换,这是真正的内存不够用了。

第六行:空行

top第七行,各进程的监控
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND

PID — 进程id
USER — 进程所有者
PR — 进程优先级
NI — nice值。负值表示高优先级,正值表示低优先级
VIRT — 进程使用的虚拟内存总量,单位kb。VIRT=SWAP+RES
RES — 进程使用的、未被换出的物理内存大小,单位kb。RES=CODE+DATA
SHR — 共享内存大小,单位kb
S — 进程状态。D=不可中断的睡眠状态 R=运行 S=睡眠 T=跟踪/停止 Z=僵尸进程
%CPU — 上次更新到现在的CPU时间占用百分比
%MEM — 进程使用的物理内存百分比
TIME+ — 进程使用的CPU时间总计,单位1/100秒
COMMAND — 进程名称(命令名/命令行)

常用的有:PID, USR, S, %CPU, %MEM, TIME+, COMMAND
交互命令:h 帮助

敲enter或space , 刷新显示
‘A’:切换交替显示模式top命令视图下,键入‘A’显示如下:

显示4个窗口:
Def (默认字段组)
Job (任务字段组)
Mem (内存字段组)
Usr (用户字段组)四组字段共有一个独立的可配置的概括区域和它自己的可配置任务区域。4个窗口中只有一个窗口是当前窗口。当前窗口的名称显示在左上方。(注:只有当前窗口才会接受你键盘交互命令)
我们可以用’a’和’w’在4个 窗口间切换。’a’移到后一个窗口,’w’移到前一个窗口。用’g’命令你可以输入一个数字来选择当前窗口。在键入‘A‘后在键入‘a‘的显示如下:

多U多核CPU监控

在top基本视图中,按键盘数字“1”,可监控每个逻辑CPU的状况:

观察上图,服务器有4个逻辑CPU,实际上是1个物理CPU。如果不按1,则在top视图里面显示的是所有cpu的平均值。

进程字段排序

默认进入top时,各进程是按照CPU的占用量来排序的,在【top视图 01】中进程ID为14210的java进程排在第一(cpu占用100%),进程ID为14183的java进程排在第二(cpu占用12%)。可通过键盘指令来改变排序字段,比如想监控哪个进程占用MEM最多,我一般的使用方法如下:
1. 敲击键盘“b”(打开/关闭加亮效果),top的视图变化如下:

我们发现进程id为12363的“top”进程被加亮了,top进程就是视图第二行显示的唯一的运行态(runing)的那个进程,可以通过敲击“y”键关闭或打开运行态进程的加亮效果。
高亮运行状态的进程 b, 然后通过y键关闭或打开运行状态进程的加亮效果
2. 敲击键盘“x”(打开/关闭排序列的加亮效果),top的视图变化如下:可以看到,top默认的排序列是“%CPU”。

3. 通过”shift + >”或”shift + <”可以向右或左改变排序列,下图是按一次”shift + >”的效果图:

改变进程显示字段 -- 这个没看懂

1. 敲击“f”键,top进入另一个视图,在这里可以编排基本视图中的显示字段:

这里列出了所有可在top基本视图中显示的进程字段,有”*”并且标注为大写字母的字段是可显示的,没有”*”并且是小写字母的字段是不显示的。如果要在基本视图中显示“CODE”和“DATA”两个字段,可以通过敲击“r”和“s”键

source, sh , bash, ./ 执行脚本的区别

source fileName
作用:在当前bash环境下读取并执行FileName中的命令。该filename文件可以无“执行权限”
注:该命令通常命令“.”来替代
如:source .bash_profile 等价于 . .bash_profile两者等效

sh和bash命令用法sh FileName
bash FileName
作用:在当前bash环境下读取并执行FileName中的命令。该fileName文件可以无“执行权限”
注:两者在执行文件时的不同,是分别用自己的shell来跑文件。
sh使用”-n”选项进行shell脚本的语法检查,使用”-x”选项实现shell脚本逐条语句的跟踪。

./的命令用法./Filename
作用:打开一个子shell来读取并执行FileName中命令。
注:运行一个shell脚本时会启动别一个命令解释器。
每个shell脚本有效地运行在父shell的一个子进程里。这个父shell是指在一个控制终端或在一个xterm窗口中给你命令指示符的进程。


./*.sh 的执行方式等价于 sh ,/*.sh 或 bash ./*.sh, 此三种执行脚本的方式都是重新启动一个子shell,在子shell中执行此脚本
source ./*.sh 和 . ./*.sh的执行方式是等价的,即两种执行方式都是在当前shell进程中执行此脚本,而不是重新启动一个shell 而在子shell进程中执行此脚本。