shell脚本检查进程PID及服务脚本编写方法

linux在做启停服务脚本时,需要检查进程PID来确认是否启/停成功,往往需要在一个脚本中多次执行同一条命令,为了方便起见,可以把检查进程PID的命令赋给一个变量,在需要用到PID的地方,直接调用变量来获取进程当前的PID。如检查redis的进程PID:

PID=`ps -ef |grep redis-server |grep -v grep |awk '{print $2}'`

通过$PID即可获取到PID,但执行了启停命令后,再调用$PID就不行了,因为$PID这个变量值还是上一次命令执行后的结果,值没有变化,需要重新执行获取PID的命令,想简单的通过$PID来获取已经行不通了。

故考虑把命令作为字符串赋给一个变量,在需要调用PID的地方,通过重新计算变量即可,而不用再去打一长串的命令,减少编写的工作量(虽然工作量也不是很大,但总觉得很low,傻傻的重复……)

总结检查进程PID的几种方法如下:

方法一:

PID=`ps -ef |grep redis-server |grep -v grep |awk '{print $2}'`
#echo $PID

注意是反引号,代表将反引号内的字符串作为命令执行。或者用$命令
PID=$(ps -ef |grep redis-server |grep -v grep |awk '{print $2}')
此方法虽能检查PID,但每次还需重复敲打一长串的命令。

方法二:

CMD="ps -C redis-server --no-header |awk '{print \$1}'"
PID=`eval $CMD`   或  PID=$(eval $CMD)
#echo $PID

将命令作为字符串赋给一个变量CMD,需要时通过执行eval $CMD即可,通过将长串命令简化为一个短命令。
双引号内的变量$1在赋值时会先转换掉,故需要用转义符\

方法三:

CMD="eval ps -C redis-server --no-header |awk '{print \$1}'"
PID=$($CMD)
或
CMD=$"eval ps -C redis-server --no-header |awk '{print \$1}'"
PID=$CMD  
#echo $PID

此方法与方法二类似,同样利用eval计算,把eval作为初始命令中的字符串,两次求变量,第一次得到完整的命令字符串,第二次执行命令得到结果。

注:

  • 单引号”的内容原样输出,双引号”“会对变量先求值再输出,故双引号内有特殊字符需用反斜杠\进行转义;
  • 含有管道符|的字符串作为串命令执行时,|会变认为是一个普通字符,起不到管道的作用,故执行命令会报错,需要采用eval来避免。

    redis服务脚本

# description: Redis Start Stop Restart Status
# processname: Redis  
# chkconfig: 2345 25 75                                         


PRG_HOME="/etc/keepalived/redis/"                               #redis主目录
PRG="redis-server"                                              #redis启动执行文件
CONFIG="redis.conf"                                             #redis配置文件
CLI="redis-cli"                                                 #redis客户端执行文件   
PWD="password"                                                  #redis密码
BOOTPRG="$PRG_HOME$PRG $PRG_HOME$CONFIG"                        #启动命令
STOPPRG="$PRG_HOME$CLI -a $PWD shutdown"                        #停止命令
CMD="eval ps -C $PRG --no-header |awk '{print \$1}'"            #进程检查
RETVAL=0                                                        #命令执行的返回结果


start()
{
PID=$($CMD)
if [[ -n $PID ]] ; then                                            #通过PID判断Redis是否在运行      
    echo "Redis is running,PID is $PID"                        
    return $RETVAL                                             
elif [ ! -f $PRG_HOME$PRG ] || [ ! -x $PRG_HOME$PRG ] || [ ! -f $PRG_HOME$CONFIG ];then    #检查是否有执行权限              
    echo "Start Redis Failed! Cannot find $PRG_HOME$PRG or does not have execute permission!"
    RETVAL=1
    return $RETVAL                                             
else
    echo $"Starting Redis..."
    $BOOTPRG                                                   
    RETVAL=$?                                                  
    sleep 1                                                     
    PID=$($CMD)
    if [[ -z $PID ]] ; then                                        
        echo "Redis Start Failed! $RETVAL"
        return $RETVAL
    fi
    echo "Start Redis Success. PID is $PID"
    return $RETVAL 
fi
}

stop()
{
PID=$($CMD)
if [[ -z $PID ]] ; then                                            
    echo "Redis is not running."    
    return $RETVAL                                             
elif [ ! -f $PRG_HOME$CLI ] || [ ! -x $PRG_HOME$CLI ];then              
    echo "Stop Redis Failed! Cannot find $PRG_HOME$CLI or does not have execute permission!"
    RETVAL=1
    return $RETVAL                                             
else
    echo "Stopping Redis..."
    $STOPPRG                                           
    RETVAL=$?                                                  
    sleep 1                                                 
    PID=$($CMD)
    if [[ ! -z $PID ]] ; then                                      
        echo "Stop Redis Failed! $RETVAL"
        return $RETVAL
    fi
    echo "Redis Stopped."
    return $RETVAL 
fi
}


restart()
{
stop
start
return $?
}

status()
{
PID=$($CMD)
if [[ -z $PID ]] ; then
    echo "Redis is not running."
    return $RETVAL
else
    echo "Redis is running,PID is $PID"
    return $RETVAL
fi
}


case $1 in  
    start)  
        start
        ;;   
    stop)     
        stop  
        ;;   
    restart)  
        restart
        ;;  
    status)  
        status
        ;;  
esac      
exit $?




服务脚本的编写方法转自:
https://blog.csdn.net/stone_wzf/article/details/45727595

chkconfig –level 345 nfs off

–add name 这个选项增加一项新的服务,chkconfig 确保每个运行级有一项 启动(S) 或者 杀死(K) 入口。如有缺少,则会从缺省的init 脚本自动建立。
–del name 用来删除服务,并把相关符号连接从 /etc/rc[0-6].d 删除。

每个被chkconfig 管理的服务需要在对应的init.d 下的脚本加上两行或者更多行的注释。
第一行告诉 chkconfig 缺省启动的运行级以及启动和停止的优先级。如果某服务缺省不在任何运行级启动,那么使用 - 代替运行级。
第二行对服务进行描述,可以用跨行注释。

例如,random.init 包含三行:

# chkconfig: 2345 20 80
# description: Saves and restores system entropy pool for
# higher quality random number generation.

表明 random 脚本应该在运行级 2,3,4,5 启动,启动优先权为20,停止优先权为80。

实例介绍: 安装Apache-ActiveMQ

#!/bin/bash
#
# chkconfig: 35 66 34
# description: Apache ActiveMQ
#

. /etc/rc.d/init.d/functions

ACTIVEMQ_USER=activemq
WORK_DIR=apache-activemq-5.4.2

case "$1" in
  start)
        su - ${ACTIVEMQ_USER} -c "cd ${WORK_DIR}; bin/activemq start"
        ;;
  stop)
        su - ${ACTIVEMQ_USER} -c "cd ${WORK_DIR}; bin/activemq stop"
        ;;
  restart|reload)
        su - ${ACTIVEMQ_USER} -c "cd ${WORK_DIR}; bin/activemq restart"
        ;;
  status)
        su - ${ACTIVEMQ_USER} -c "cd ${WORK_DIR}; bin/activemq status"
        ;;
  *)
        echo $"Usage: $0 {start|stop|restart|reload}"
        exit 2
esac

exit $RETVAL

将此脚本cp到/etc/init.d/里面后,cp activemq /etc/init.d/
运行:
chkconfig –add
chkconfig –add activemq
这里的script_name要与/etc/init.d/下的相同。添加后,此命令会根据你在脚本中定义的三项数字来设定:
1)35 :runlevel,
2)66 :启动顺序
3)34 :shutdown顺序

chkconfig –add 其实就是执行了下面的语句:

ln -s /etc/rc.d/init.d/activemq /etc/rc.d/rc3.d/S66activemq 
ln -s /etc/rc.d/init.d/activemq /etc/rc.d/rc0.d/K34activemq

大写的S,代表start,其后紧跟启动顺序数字,然后是service name. 大写的K,代表kill,K或S后面的数字表示执行顺序,数字小的先执行。

# ls /etc/rc.d/rc0.d/ -l|grep act  
lrwxrwxrwx 1 root root 18 Jun 28 15:17 K34activemq -> ../init.d/activemq

chkconfig –add activemq 我怎么没看到添加K34activemq的链接呢? 是要执行
chkconfig –level 35 activemq off 后才有:

# ll /etc/rc.d/rc3.d/|grep acti
lrwxrwxrwx 1 root root 18 Jun 28 15:59 K34activemq -> ../init.d/activemq

并且同时将删除启动链接.

如果你要删除/etc/init.d/下面的脚本,chkconfig –del 即可。
但是你不想删除该脚本,仅仅是让它不要开机启动,出了上面的chkconfig off命令外,也可以直接将
/etc/rc.d/rc[2-5].d/下面对应的S开头的链接改名为小写s开头即可.

系统在进入一个运行级别时,首先将该运行级别对应的目录中以K开头的脚本按设定顺序执行,然后再将以S开头的脚本按顺序执行。

===============================================
关机执行任务与开机有点儿不同,很多人以为运行级别目录里以K开头的会在关机时执行,其实不然,(2)里面已经说的很清楚了,正确的设置关机执行任务的步骤如下:

将要执行的任务携程脚本,加上可执行权限,放在/etc/init.d目录中如/etc/init.d/stopftp.sh
cd到关闭系统所对应的运行级别目录/etc/rc0.d目录中,看一下S后面的数字,选取一个闲置的合适的数字
建立从/etc/init.d/stopftp.sh到/etc/rc0.d的软连接,代码如下:

sudo ln -s /etc/init.d/stopftp.sh /etc/rc0.d/S24stopftp
这样就可以了,如果想在执行重启的时候也执行这个脚本,就用同样的方式建立一个到/etc/rc6.d/的软连接。

(5) 启动脚本的写法

用编辑器随便打开一个/etc/init.d目录里的启动脚本,会发现主代码段都是下面这种结构:

...
case "$1" in
    start)
        do start-thing;
        ;;
    stop)
        do stop-thing;
        ;;
    restart)
        do restart-thing;
        ;;
    ...
esac

为什么要这样写呢?你如果按这种结构写个启动脚本测试一下就会发现,若该脚本的软连接以S开头,则系统启动的时候执行start-thing代码段,若该脚本的软连接以K开头的话,则系统启动时执行stop-thing代码段(有一点儿例外的是运行级别0,因为0级别是关闭系统,所以/etc/rc0.d/下的以S开头的软连接也执行stop-thing段)。是不是很智能化,所以如果可以的话启动脚本最好写标准一些。如果你非写成普通的脚本,就几个命令,没有上面那个结构,建立以K或S开头的软连接会怎么执行呢?答案是全部执行。

http://cqulpj.blogbus.com/logs/68406641.html

============================================

linux不能自动关闭rc0.d目录下K开头程序的解决
以前找了很久,都没找到不能自动关闭k开头程序的解决办法,今天无意间看到一篇文章。试验了下,果然灵。
步骤如下:
先写一个脚本放在/etc/rc.d/init.d下,chmod -f 777 , 再
ln -s /etc/rc.d/init.d/script_name /etc/rc.d/rc0.d/K01script_name
ln -s /etc/rc.d/init.d/script_name /etc/rc.d/rc6.d/K01script_name,同时也要
ln -s 到 /etc/rc.d/rc3.d/S99script_name 与/etc/rc.d/rc5.d/S99script_name。
K开头的代表系统关闭的时候执行,S开头的代表开机的时候执行。注意服务器脚本编写的规范,因为有K开通的软链接并不一定会在关机的时候自动去执行,这是为什么呢?刚开始一直没搞明白,后来从网上看到,执行K脚本的时候会查询/var/lock/subsys/下是否有与K开头脚本同名的空文件名,如果没有就不去执行,所以要按照服务器脚本编写的规范,启动的时候要在/var/lock/subsys/先touch一个与K01后面同名的空文件.同时也要调用/etc/rc.d/init.d/functions能够接受start与stop命令信号,具体可以参考/etc/rc.d/rc文件

用/etc/rc.d/init.d/functions能够接受start与stop命令信号的意思是指
你在/etc/init.d/中的那个程序可以接受start和stop参数

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值