总结下日常工作中常用的linux下的shell脚本。
linux的shell脚本很强大,可以用来做一些特殊功能。shell脚本语法虽然很简单,但是有时候把经常忘,还得再写一遍且验证ok才能用,这里总结下留作备忘。
关于shell脚本的学习觉得不需要太刻意,根据需要来。看的多用的多了自然就会了,至少能看懂吧。
启用硬件IO口
enGPIO.sh
#!/bin/sh mygpioPath1="/sys/class/gpio/gpio115" mygpioPath2="/sys/class/gpio/gpio116" buzzGPIO="/sys/class/gpio/gpio15" qrd_pwr="/sys/class/gpio/gpio121" power_down="/sys/class/gpio/gpio128" touch_key="/sys/class/gpio/gpio112" oth_pwr="/sys/class/gpio/gpio130" echo "shell exec open..." #enable voice if [ ! -d "$mygpioPath1" ]; then echo 115 > /sys/class/gpio/export fi if [ -d "$mygpioPath1" ]; then echo "out" > "/sys/class/gpio/gpio115/direction" echo "1" > "/sys/class/gpio/gpio115/value" fi #enable voice #if [ ! -d "$mygpioPath2" ]; then # echo 116 > /sys/class/gpio/export #fi #if [ -d "$mygpioPath2" ]; then # echo "out" > "/sys/class/gpio/gpio116/direction" # echo "1" > "/sys/class/gpio/gpio116/value" #fi #enable buzzse if [ ! -d "$buzzGPIO" ]; then echo 15 > /sys/class/gpio/export fi if [ -d "$buzzGPIO" ]; then echo "out" > "/sys/class/gpio/gpio15/direction" echo "0" > "/sys/class/gpio/gpio15/value" fi if [ ! -d "$qrd_pwr" ]; then echo 121 > /sys/class/gpio/export fi if [ -d "$qrd_pwr" ]; then echo "out" > "/sys/class/gpio/gpio121/direction" echo "0" > "/sys/class/gpio/gpio121/value" fi #enable power down check if [ ! -d "$power_down" ]; then echo 128 > /sys/class/gpio/export fi if [ -d "$power_down" ]; then echo "in" > "/sys/class/gpio/gpio128/direction" fi #enable touch key check if [ ! -d "$touch_key" ]; then echo 112 > /sys/class/gpio/export fi if [ -d "$touch_key" ]; then echo "in" > "/sys/class/gpio/gpio112/direction" fi #enable oth_pwr if [ ! -d "$oth_pwr" ]; then echo 130 > /sys/class/gpio/export fi if [ -d "$qrd_pwr" ]; then echo "out" > "/sys/class/gpio/gpio130/direction" echo "0" > "/sys/class/gpio/gpio130/value" fi
开机后应用启动其它应用服务
int main(int argc, char ** argv) { printf("main\n"); system("../opt/enGPIO.sh"); system("killall -9 monitor"); //启动监控服务monitor进程 system("../opt/startmonitor.sh"); }
startmonitor.sh
#!/bin/bash fileName="/app/city_app/opt/monitor" buzzGPIO="/sys/class/gpio/gpio15" #enable buzzse for notifying success function beep_notify() { if [ ! -d "$buzzGPIO" ]; then echo 15 > /sys/class/gpio/export fi if [ -d "$buzzGPIO" ]; then echo "out" > "/sys/class/gpio/gpio15/direction" echo "1" > "/sys/class/gpio/gpio15/value" sleep 1 echo "0" > "/sys/class/gpio/gpio15/value" fi } function CheckProcess() { PROCESS_NUM=`ps | grep "$1" | grep -v "grep" | wc -l` return $PROCESS_NUM } if [ ! -f $fileName ]; then echo "error!monitor exe not exit!" exit 1 else echo "find monitor exe,begin start..." CheckProcess monitor if [ $? -eq 0 ];then echo "no monitor progress find!" else echo "find monitor,..." killall -9 monitor sleep 1 fi cd /app/city_app/opt/ ./monitor & echo "start ok" beep_notify exit 0 fi
触发执行其它应用
如uplog.sh,触发ftp应用上传日志文件
#!/bin/sh echo "upload log to ftp server..." echo $1 if [ -z $1 ]; then today=`date +"%Y%m%d"` else today=$1 fi echo $today function getfname() { echo $1 filename=$(find /log/ -name "$1") echo $filename return 0 } #filename="find ./ -name "*${today}.log"" #echo $filename getfname *${today}.log echo $filename ../opt/ftp -ftpcfg=/../opt/ftpcfg.ini -fname=$filename
拷贝U盘中的文件到设备中
setconfig.sh,把U盘根目录下的config.ini文件拷贝到设置的指定目录下。
#!/bin/bash usbPath="/media/usb" fileName="/media/usb/config_up.ini" buzzGPIO="/sys/class/gpio/gpio15" #enable buzzse for notifying success function beep_notify() { if [ ! -d "$buzzGPIO" ]; then echo 15 > /sys/class/gpio/export fi if [ -d "$buzzGPIO" ]; then echo "out" > "/sys/class/gpio/gpio15/direction" echo "1" > "/sys/class/gpio/gpio15/value" sleep 1 echo "0" > "/sys/class/gpio/gpio15/value" fi } setconfig() { echo "find usb device,begin copy config_ini..." if [ ! -f $fileName ]; then echo "config file not exit!" return 1 else cp $fileName /app/city_app/etc/ return 0 fi } if [ -d "$usbPath" ]; then setconfig if [ $? -ne 0 ] ;then echo "faild to set config" exit 1 fi beep_notify beep_notify beep_notify echo "set ok" exit 0 else echo "no usb device found!" exit 1 fi
拷贝U盘数据
#!/bin/bash usbPath="/media/usb" fileName="/media/usb/qrlinux" dbName="/app/city_app/opt/bus.db" buzzGPIO="/sys/class/gpio/gpio15" #enable buzzse for notifying success function beep_notify() { if [ ! -d "$buzzGPIO" ]; then echo 15 > /sys/class/gpio/export fi if [ -d "$buzzGPIO" ]; then echo "out" > "/sys/class/gpio/gpio15/direction" echo "1" > "/sys/class/gpio/gpio15/value" sleep 1 echo "0" > "/sys/class/gpio/gpio15/value" fi } function CheckProcess() { PROCESS_NUM=`ps | grep "$1" | grep -v "grep" | wc -l` return $PROCESS_NUM } copydata() { echo "find usb device,begin copy data..." if [ ! -f $dbName ]; then echo "db file not exit!" return 1 else cp -v /app/city_app/opt/bus.db /media/usb/ cd /media/usb/ ls -l return 0 fi } if [ -d "$usbPath" ]; then copydata if [ $? -ne 0 ] ;then echo "faild to copy data" fi else echo "no usb device found!" exit 1 fi if [ ! -f $fileName ]; then echo "qrlinux file not exit!" else echo "find qrlinux file,begin updata..." CheckProcess qrlinux if [ $? -eq 0 ];then echo "no qrlinux progress find!" else echo "find qrlinux,..." killall -9 qrlinux sleep 2 fi cp -v $fileName /app/city_app/opt/ cd /app/city_app/opt/ ls -l echo "cp ok" umount /media/usb/ beep_notify exit 0 fi
Linux应用开机自启动
/etc/init.d/文件夹下放置有很多常用服务的控制脚本和其他的一些脚本。
K开头的脚本文件代表运行级别加载时需要关闭的,S开头的代表需要执行。
因此当我们需要开机启动自己的脚本时,只需要将可执行脚本丢在/etc/init.d目录下,然后在/etc/rc.d/rc*.d中建立软链接即可。如:
[root@localhost ~]# ln -s /etc/init.d/sshd /etc/rc.d/rc3.d/S100ssh
sshd是具体服务的脚本文件,S100ssh是其软链接,S开头代表加载时自启动
如果需要在多个运行级别下设置自启动,则需建立多个软链接。
Linux的引导过程
系统启动之后,在进入init.d之前,我们先来看看系统都做了什么工作。系统加电之后,首先进行的硬件自检,然后是bootload对系统的初始化,加载内核。
内核被加载到内存之后,就开始执行了。一旦内核启动运行,对硬件的检测就会决定需要对哪些设备驱动进行初始化。
从这开始内核就能够挂装根文件系统。内核挂装了根文件系统,并已初始化所有的设备驱动程序和数据结构等之后,就通过启动一个叫init的用户级程序,完成引导进程。
Init进程是系统启动之后的第一个用户进程,所以它的pid(进程编号)始终为1。init进程上来首先做的事是去读取/etc/目录下inittab文件中initdefault id值,这个值称为运行级别(run-level)。它决定了系统启动之后运行于什么级别。运行级别决定了系统启动的绝大部分行为和目的。
这个级别从0到6 ,具有不同的功能。不同的运行级定义如下:
0 – 停机(千万别把initdefault设置为0,否则系统永远无法启动)
1 – 单用户模式,root权限,用于系统维护,禁止远程登陆
2 – 多用户状态,没有 NFS
3 – 标准多用户模式,登陆后进入命令行模式
4 – 系统未使用,保留
5 – 多用户图形模式,登陆后进入图形GUI模式
6 – 重新启动(千万不要把initdefault 设置为6,否则将一直在重启 )
服务器一般都是命令行模式,所以默认运行级别为 3
如何添加自启程序?
(1)/etc/init.d 目录中添加
以启动SVN为例
1)在 /etc/init.d 目录下创建启动服务的脚本
vim /etc/init.d/svn #!/bin/bash svnserve -d -r /svn仓库路径
设置执行权限
chmod 755 /etc/init.d/svn
2)把这个脚本软链接到 /etc/rc.d/rc3.d
ln -s /etc/init.d/svn /etc/rc.d/rc3.d/S101svn
S 代表是要执行这个脚本,101 是执行顺序,通常要大于60,这样可以保证基础服务都已经启动完成
重启linux测试
(2)/etc/rc.local 文件中添加
直接修改 /etc/rc.local
该脚本是在系统初始化级别脚本运行之后再执行的,因此可以在里面添加想在系统启动之后执行的脚本
(3)chkconfig 命令添加
如何禁止自启程序?
(1)直接删除 /etc/rc.d/rcN.d 目录的目标链接文件
(2)删除 /etc/rc.local 文件中定义的启动脚本
(3)查看自启动服务列表,从中选择目标服务执行禁止操作
chkconfig –list
chkconfig –del 服务名
init.d里面放的都是什么东西。这个目录存放的是一些脚本,一般是linux以rpm包安装时设定的一些服务的启动脚本。系统在安装时装了好多rpm包,这里面就有很多对应的脚本。执行这些脚本可以用来启动,停止,重启这些服务。
前面说到,/etc/rc.d/init.d这个目录下的脚本就类似与windows中的注册表,在系统启动的时候执行。程序运行到这里(init进程读取了运行级别),该行/etc/rc.d/init.d里面的脚本,但是并不是直接运行,而是有选择的因为系统并不需要启动所有的服务。
系统是如何选择哪些需要启动哪些不需要启动?运行级别就起作用了。在决定了系统启动的run level之后,/etc/rc.d/rc这个脚本先执行。在有些linux源码中它都是一上来就check_runlevel(),知道了运行级别之后,对于每一个运行级别,在rc.d下都有一个子目录分别是rc0.d,rc1.d ….. rc6.d。每个目录下都是到init.d目录的一部分脚本一些链接。每个级别要执行哪些服务就在相对应的目录下,比如级别5要启动的服务就都放在rc5.d下,但是放在这个rc5.d下的都是一些链接文件,链接到init.d中相对应的文件,真正干活到init.d里的脚本。
/etc/init.d里面还放置了一些脚本可以用来管理服务用。比如:
可以使用start,stop,restart选项。例如,如果你想关闭网络,你可以使用如下形式的命令:
/etc/init.d/networking stop
又比如,你改变了网络设置,并且需要重启网络。你可以使用如下命令:
/etc/init.d/networking restart
rc.local也是经常使用的一个脚本。该脚本是在系统初始化级别脚本运行之后再执行的,因此可以安全地在里面添加你想在系统启动之后执行的脚本。
rc和rcS脚本
#!/bin/sh # # rc This file is responsible for starting/stopping # services when the runlevel changes. # # Optimization feature: # A startup script is _not_ run when the service was # running in the previous runlevel and it wasn't stopped # in the runlevel transition (most Debian services don't # have K?? links in rc{1,2,3,4,5} ) # # Author: Miquel van Smoorenburg <miquels@cistron.nl> # Bruce Perens <Bruce@Pixar.com> # # Version: @(#)rc 2.78 07-Nov-1999 miquels@cistron.nl # . /etc/default/rcS export VERBOSE startup_progress() { step=$(($step + $step_change)) if [ "$num_steps" != "0" ]; then progress=$((($step * $progress_size / $num_steps) + $first_step)) else progress=$progress_size fi #echo "PROGRESS is $progress $runlevel $first_step + ($step of $num_steps) $step_change $progress_size" if type psplash-write >/dev/null 2>&1; then TMPDIR=/mnt/.psplash psplash-write "PROGRESS $progress" || true fi #if [ -e /mnt/.psplash/psplash_fifo ]; then # echo "PROGRESS $progress" > /mnt/.psplash/psplash_fifo #fi } # # Start script or program. # startup() { # Handle verbosity [ "$VERBOSE" = very ] && echo "INIT: Running $@..." case "$1" in *.sh) # Source shell script for speed. ( trap - INT QUIT TSTP scriptname=$1 shift . $scriptname ) ;; *) "$@" ;; esac startup_progress } # Ignore CTRL-C only in this shell, so we can interrupt subprocesses. trap ":" INT QUIT TSTP # Set onlcr to avoid staircase effect. stty onlcr 0>&1 # Limit stack size for startup scripts [ "$STACK_SIZE" == "" ] || ulimit -S -s $STACK_SIZE # Now find out what the current and what the previous runlevel are. runlevel=$RUNLEVEL # Get first argument. Set new runlevel to this argument. [ "$1" != "" ] && runlevel=$1 if [ "$runlevel" = "" ] then echo "Usage: $0 <runlevel>" >&2 exit 1 fi previous=$PREVLEVEL [ "$previous" = "" ] && previous=N export runlevel previous # Is there an rc directory for this new runlevel? if [ -d /etc/rc$runlevel.d ] then # Find out where in the progress bar the initramfs got to. PROGRESS_STATE=0 #if [ -f /dev/.initramfs/progress_state ]; then # . /dev/.initramfs/progress_state #fi # Split the remaining portion of the progress bar into thirds progress_size=$(((100 - $PROGRESS_STATE) / 3)) case "$runlevel" in 0|6) # Count down from -100 to 0 and use the entire bar first_step=-100 progress_size=100 step_change=1 ;; S) # Begin where the initramfs left off and use 2/3 # of the remaining space first_step=$PROGRESS_STATE progress_size=$(($progress_size * 2)) step_change=1 ;; *) # Begin where rcS left off and use the final 1/3 of # the space (by leaving progress_size unchanged) first_step=$(($progress_size * 2 + $PROGRESS_STATE)) step_change=1 ;; esac num_steps=0 for s in /etc/rc$runlevel.d/[SK]*; do case "${s##/etc/rc$runlevel.d/S??}" in gdm|xdm|kdm|reboot|halt) break ;; esac num_steps=$(($num_steps + 1)) done step=0 # First, run the KILL scripts. if [ $previous != N ] then for i in /etc/rc$runlevel.d/K[0-9][0-9]* do # Check if the script is there. [ ! -f $i ] && continue # Stop the service. startup $i stop done fi # Now run the START scripts for this runlevel. for i in /etc/rc$runlevel.d/S* do [ ! -f $i ] && continue if [ $previous != N ] && [ $previous != S ] then # # Find start script in previous runlevel and # stop script in this runlevel. # suffix=${i#/etc/rc$runlevel.d/S[0-9][0-9]} stop=/etc/rc$runlevel.d/K[0-9][0-9]$suffix previous_start=/etc/rc$previous.d/S[0-9][0-9]$suffix # # If there is a start script in the previous level # and _no_ stop script in this level, we don't # have to re-start the service. # [ -f $previous_start ] && [ ! -f $stop ] && continue fi case "$runlevel" in 0|6) startup $i stop ;; *) startup $i start ;; esac done fi
#!/bin/bash #myapp application start mechnism #manu run myapp #set -e curdir=$(pwd) myapp_city_app_name=city_app #search executable file in bin directory #and start the file. #the file number must be only one!!!! function searchBinAndRun() { # echo "searchBinAndRun...enter" path=$1 cd $path if [ ! -d bin ]; then echo "no bin directory ..." return 1 fi cd bin files=$(ls $path/bin) echo "path= $path" for filename in $files do echo $filename if [ ! -d $filename ]; then chmod 777 $filename #./$filename & ./$filename return 0 fi done return 1 } #set env variable for application function setAppEnv() { # echo "setAppEnv...enter" path=$1 echo "path= $path" if [ -d lib ]; then cd lib export LD_LIBRARY_PATH=$(pwd) #echo "LD_LIBRARY_PATH=$LD_LIBRARY_PATH" fi } #start myapp specified application #after opkg the app ipk function startmyappApp() { echo "startmyappApp...start" if [ $# -lt 1 ] ; then echo "para is not enough!!,quit" return 1 fi appname=$1 cd /app #echo "---->$appname" if [ -d $appname ]; then cd $appname #echo "pwd = $(pwd)" setAppEnv /app/$appname if searchBinAndRun /app/$appname ; then echo "$appname starts success" return 0 else echo "$appname starts error" return 1 fi else echo "$appname dir isnot exist!!" return 1 fi } # ###myapp start main # #######try to start myapp customersized app######## ####monitor myapp-app,may be restarted!!############ echo "2--->try to start customersized app....." startmyappApp $myapp_city_app_name exit 0