目录

脚本

程序员经常会使用脚本来方便自己的开发,不过本人脑子记性不好,在此记录一些经常使用的模板。

bash

文本处理

逐行读取文件

FILE=/home/user/file.txt
cat $FILE | while read line
do
    echo "line: $line"
done

Json 数据解析

先下载了一个工具:jq

echo "{\"firstName\": \"John\",\"lastName\": \"Smith\"}" | jq '.firstName'

数据计算

浮点除法需要设置小数点位数

echo "scale=10; 89.0 / 1000" | bc

数据比较

V=-120.12
echo "$V < -180.0" | bc

时间转换

ts -> time
date -d @12313 +"%F %T"

控制输入

输入参数

if [ -z $1 ]; then
    echo $"Usage: $0 in"
    exit 1
fi
echo "in: $1"

等待输入参数:

if read -t 10 -p "wait input: " indata ## 10 秒超时
then
    echo "input:$indata"
else
    echo "timeout"
fi

判断权限

if [[ $EUID -ne 0 ]]; then
    echo Only root can access run
    exit 1
fi

命令选择

rc=0
case "$1" in
    hello)
        echo "hello world"
    ;;
    *)
        echo $"Usage: $0 {hello}"
        exit 2
esac

exit $rc

判断运行结果

do_or_die()
{
    eval $* || exit $?
}

do_or_die echo "Hello"

多次尝试

RET=0
result() {
    eval $*
    RET=$?
}
loop() {
    n=0
    until [ $n -ge 3 ]
    do
        echo "TRY IT $n TIMES ..."
        result $*
        if [ $RET == 0 ]; then
            break
        fi
        echo "RET IS $RET ..."
        n=$[$n+1]
    done
}

expect

交互式脚本常用,调试可加上 -d 参数定位问题原因

常用

函数

proc func_name { argc } {
    puts $argc
}
func_name "hello"

如果多个函数公用一个 spawn 怎么办?
一种是使用 upvar spawn_id 引入全局变量1

proc expect_prompt {} {
    upvar spawn_id spawn_id
    expect -re {bash-[.0-9]+[#$] $}
}

proc open_conn {} {
    upvar spawn_id spawn_id
    spawn bash --noprofile --norc
    expect_prompt
}

proc close_conn {} {
    upvar spawn_id spawn_id
    send "exit\r"
    expect eof
}

proc send_cmd { cmd } {
    upvar spawn_id spawn_id
    send "$cmd\r"
    expect_prompt
}

proc main {} {
    open_conn

    send_cmd "echo spawn_id=$spawn_id"
    send_cmd "ps Tu"

    close_conn
}

main

另一种是函数只对 expect 结果进行处理:

proc func {} {
    expect {
        "xx" { return 0 }
    }
    return 1
}

spawn xx
if {[func]} {
    puts "ERROR"
    exit 1
}
expect eof
exit 0

循环

for {set i 0} {$i < 5} {incr i} {
    puts "$i"
}

判断

if { true } {
    puts "true"
} else {
    puts "false"
}

interact2

在结尾加上 interact 表示把控制权交给用户

在 shell 脚本中引用

WORD="hello"
expect <<-EOF
set timeout 10
puts $WORD
puts \$timeout
expect eof
EOF

注意变量和一些特殊字符转义问题

两步验证3

需要安装 oathtool

spawn ssh $USER@$IP
expect {
   "(yes/no)?" { send "yes\r"; exp_continue }
    "Verification code:" {
        set verifi_code [exec oathtool --totp -b -d 6 $SECRETE_KEY]
        send "\$verifi_code\r"; exp_continue
    }
    "password:" { send "$PASSWD\r" }
    timeout { exit 127 }
}
expect eof
catch wait result
exit [lindex \$result 3]

获取输入参数4

set user [lindex $argv 0]
set ip   [lindex $argv 1]
set len  [llength $argv]