最近做shell脚本,出现了一些问题,在这里记录一下:
1、判断一个文件是否存在,最常用的方法还是file判别中的
if [ -e filename ]; then
echo "exit!"
else
echo "nonexit!"
fi
2、函数编写的格式:
function(){ //定义与编辑函数
...
...
}
function //引用函数,注意,引用函数的过程不需要加“()”。
3、想要实现scp自动上传,最便捷的方法是使用expect软件,如果在嵌入式上运行自动认证,则需要先移植该软件,移植expect软件链接不好找,这里献上链接(花很长时间才找到!)
http://blog.sina.com.cn/s/blog_43ffbf3e0101afir.html
expect指令想要简单使用的话比较简单,它是tcl指令体系中的东西,所以一般在bash下是无法执行的。
关于expect的学习可以参考经典:Exploring Expect
这个链接也可以考虑:
expect一共会产生两个进程,一个进程是执行命令的进程(spawn语句产生的进程);另一个是模拟用户(expect语句产生的进程)。
send就是模拟用户在console下输入字符串,我们输入命令都要回车的,相应的send的字符串要用\r结束。
expect使用最多的三个指令:
spawn+command:run the command
expect +“sentense”:check if the sentense come up
send “command\n”:input the command as the last sentense‘s reply
此外,通常用来等待的语句
set timeout +n:waiting for n milliseconds
4、在执行expect语句时,由于上述语言都要在expect环境下执行,所以bash程序中的变量如何在expect程序中引用,请看下面的方法:
expect<<-END
...
...
expect eof
END
即可,将本条结合第二条就可以达到bash程序中的函数中引用expect指令的作用,同时还能达到expect引用程序中的变量的效果
5、linux中批量注释的方法:
<<MULTILINECOMMENT
...
...
MULTILINECOMMENT
6、expect在输出字符上,本应参考explore expect,但是还有一个笨办法:
send每个特殊字符前面都加上\就可以了,expect每个特殊字符前面加上\\\,此方法来自该链接:
http://www.newsmth.net/nForum/#!article/LinuxDev/20758
可以以下列语句做验证
send "\$ax\[sdf\]\@\#\r"
expect "\\\r\\\n"
但是,本人的测试场景是调用函数中的测试,和上面稍稍有一些区别,放上一点代码:
#!/bin/bash
test(){
expect<<-END
send $1
expect eof
END
}
filename=dmesg\\\[3\\\].txt
test $filename
本程序中传递的参数中含有特殊字符,需要“\\\”才能完成特殊字符显示,根据该链接的验证,我猜想应该是因为变量是被expect调用,所以尽管在send中被调用,仍然使用了\\\,读者若是知道原因,欢迎留言,本人若今后有时间一读explore expect,也会对此博客做更新。
7、脚本执行的命令必须在脚本开头的PATH=..中包含该命令的绝对路径,这一点在嵌入式实现中非常重要。
测试scp指令的嵌入式执行。
which scp,输出结果
/usr/local/bin/scp
添加到path中去,
PATH=...:...:/usr/local/bin
下面就可以正常实现scp指令了。
8、使用cron来完成自动周期上传信息的功能。
crontab -e用来编辑需要自动完成的指令,通常的格式是
* * * * * command
前五个星号在其后分别添加分时日年等日期信息,如果想要周期执行则在其后添加“/intervel”,command部分可以填写需要执行的某条指令,也可以填写脚本的名称,如/home/upload.sh
具体可以详见如下链接:
http://www.cnblogs.com/youyou/archive/2007/01/20/625365.aspx
http://www.cnblogs.com/aix1314/archive/2013/03/20/2971004.html
编辑完成后使用crontab -l查看是否编辑正确,最后运行cron/crond start启动周期执行。在嵌入式linux和PC的linux中有些微的区别,具体可以输入cron 再敲tab键看看各自系统中是哪一个指令。关闭cron的方式一般来说是cron/crond stop,但是一般都关闭不成功,所以需要将进程直接关闭,查看进程的方法是 pgrep cron,直接kill `pgrep cron`相应关闭即可。
此外,查看进程是否周期执行的方式可以到日志中查询,在嵌入式linux中可以查看/var/log/message中查看是否存在cron的指令执行,在PClinux中可以查看/var/log/system.log中是否存在和cron相关的执行日志。
另外:注意,嵌入式linux系统cron的执行需要目录:/var/spool/cron/crontabs,所需需要手动建立该目录。
9、前述提到expect的用法,由于如果是第一次scp,在过程中认证不能建立,会出现询问是否要继续连接,这是需要填写yes/no,之后再填密码,因此涉及到expect的case选择,在此,我们使用了expect的选择语句,建立例程如下:
server.sh
#!/bin/bash
echo "*******************************"
echo " ***************************"
echo "A:The authenticity of host '192.168.2.1 (192.168.2.1)' can't be established.
echo "Are you sure you want to continue connecting (yes/no)?"
read choice
echo "A:server@192.168.2.1's password:"
read password
if [ "$password" == "password" ];then
echo "A:passed"
read answ
else
echo "A:failed"
read fail
fi
echo " ***************************"
echo "*******************************"
host.sh
#!/bin/bash
function_test(){
expect<<-END
spawn ./talk.sh
expect {
"Are you sure you want to continue connecting (yes/no)?"{send "yes\r";exp_continue}
"server@192.168.2.1's password:"{send "password\r"}
}
expect {
"passed"{send "It worked!\r"}
"failed" {send "It doesn't worked!\r"}
}
expect eof
exit
END
}
function_test
10、变量嵌套
为了使变量中嵌套变量,需要使用eval来完成嵌套,eval完成的功能是对命令的二次扫扫描,例如:
test_1=test
option=1
echo $option_$test #return $option,that is 1
eval echo \$test_$option #return $test_1