脚本

本文最后更新于:2020年9月9日 下午

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

bash

文本处理

逐行读取文件

1
2
3
4
5
6
FILE=/home/user/file.txt
cat $FILE | while read line
do
echo "line: $line"
done

Json 数据解析

先下载了一个工具:jq

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

数据计算

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

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

数据比较

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

时间转换

ts -> time

1
date -d @12313 +"%F %T"

控制输入

输入参数

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

等待输入参数:

1
2
3
4
5
6
if read -t 10 -p "wait input: " indata # 10 秒超时
then
echo "input:$indata"
else
echo "timeout"
fi

判断权限

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

命令选择

1
2
3
4
5
6
7
8
9
10
11
rc=0
case "$1" in
hello)
echo "hello world"
;;
*)
echo $"Usage: $0 {hello}"
exit 2
esac

exit $rc

判断运行结果

1
2
3
4
5
6
do_or_die()
{
eval $* || exit $?
}

do_or_die echo "Hello"

多次尝试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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 参数定位问题原因

常用

函数

1
2
3
4
proc func_name { argc } {
puts $argc
}
func_name "hello"

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
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 结果进行处理:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
proc func {} {
expect {
"xx" { return 0 }
}
return 1
}

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

循环

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

判断

1
2
3
4
5
if { true } {
puts "true"
} else {
puts "false"
}

interact2

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

在 shell 脚本中引用

1
2
3
4
5
6
7
WORD="hello"
expect <<-EOF
set timeout 10
puts $WORD
puts \$timeout
expect eof
EOF

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

两步验证3

需要安装 oathtool

1
2
3
4
5
6
7
8
9
10
11
12
13
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

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

脚本
https://wishlily.github.io/article/linux/2016/11/30/undefined/
作者
Wishlily
发布于
2016年11月30日
许可协议