牵牛花大神
(牵牛花大神)
1
希望厉害的你能帮助我。
我的脚本 myscript.sh 调用脚本 closeSybase.sh,
脚本 myscript.sh 里面的除了调用 closeSybase.sh 外,还用来检测 sybase 运行状态,
脚本 closeSybase.sh 的功能是关闭 sybase 数据库,
那么问题是:
我手工执行脚本 myscript.sh 时,它调用脚本 closeSybase.sh 关闭数据库执行后,在 myscript.sh 里面的语句检测 sybase 已经关闭。
而 shutdown 关机触发执行 myscript.sh 的场景下就不好使了,因为 myscript.sh 脚本里面的判断语句检测到数据库始终是运行的(我让脚本打了日志,在日志里面看到的始终是运行的)。
诡异的地方还有:如果把以上两个脚本功能合写在一个脚本里,那么关闭 sybase 的语句执行后,后面检测 sybase 运行与否的语句的检测结果却始终是运行的,无法得到更新的 sybase 运行状态
难道这是脚本的坑吗
贴脚本内容,以及“shutdown 关机触发执行 myscript.sh”具体是怎么实现的
牵牛花大神
(牵牛花大神)
3
由于代码和日志全在公司内网里,外网无法获取,不可以拷贝,否则违规,后果严重,所以我在这里只能详述一下:
shutdown 关机触发执行 myscript.sh”具体实现: 参照资料:SysVinit 引导脚本 - openSUSE
一:将 myscript.sh 脚本按照 LSB 规范书写:
脚本头部添加注释信息:
### BEGIN INIT INFO
# Provides: qnhds // 指定服务名,可以通过 chkconfig --list 查看服务,如果成功注册为服务,可以看到服务名:qnhds
# Required-Start: // 指定运行此脚本必须运行 (是必须运行) 着的服务,这里没有指定
# Should-Start: nms sybase // 指定运行此脚本需要运行 (不是必须运行) 着的服务是 nms 和 sybase 服务
# Required-Stop: // 指定运行此脚本必须停止 (是必须停止) 的服务,这里没有指定
# Should-Stop: // 指定运行此脚本需要停止 (不是必须运行) 的服务,这里没有指定
# Default-Start: 0 6 // 这一行注释信息指定了默认启动脚本的运行级别是 0 和 6,即是重启或关机时触发 myscript.sh 的执行
# Default-Stop:
# Short-Description: Sound daemon with network support
# Description: stop the nms and sybase service
### END INIT INFO
二:将 myscript.sh 脚本放到 /etc/init.d/ 目录下
三:cd /etc/init.d/ , 执行命令:chkconfig --add myscript.sh
四:cd /etc/init.d/ , 执行命令:insserv myscript.sh
做完以上步骤,就成功地把 myscript.sh 脚本注册为系统服务,并且是开机时 / 关机时启动。
该脚本打印了详细的操作日志,并且打印了 isql 连接数据库、执行停止 sybase 的详细日志。
手动执行 myscript 脚本时,可以正常运行,并且成功执行关闭 sybase 数据库的语句,随后的语句判断 sybase 数据库的状态是停止。从日志里看到的,一切正常,实现了编程目的。
但是在命令行里执行:shutdown -r now 命令时,suse 系统成功重启后,通过查看 myscript 的操作日志,发现 脚本中判断 sybase 运行状态的语句打印的日志显示:sybase 数据库是运行的,日志其他部分与手动执行产生的日志一样,没有区别。这就奇怪了,为什么在手动执行 myscript 脚本的时候可以实现停止 sybase,而 shutdown 触发执行它的时候就得不到数据库停止的结果?
@牵牛花大神
Hi,具体脚本看不到我理解,我现在想知道几件事:
-
myscript 是怎么检测 Sybase 是否在运行的,通过进程?通过 PID 文件?通过 socket?
-
执行 closeSybase 后,你有没有加 wait?Systemd 是并发的…看你的描述我感觉是 closeSybase 执行后就不管它,直接去取状态了。
-
Systemd 关机时服务的执行顺序跟开机是反的,你的 myscript 是在 ExecStart 里调用的还是在 ExecStop 里调用的?正常是 ExecStop 里。所以你的 myscript 脚本的 stop block 是怎么写的?不会写到 start block 里去了吧?因为 systemd 对 sysvinit 脚本的兼容是 start 对应 ExecStart,stop 对应 ExecStop,然后你的脚本只管关机,你觉得在 start 里执行就好。
Sybase 是闭源的,不过我们可以用 mysql 之类的来模拟的。问题是能够得到解决的,但你的让我们能够模拟出来…
从我的 iPhone 发送,使用 Tapatalk
另外,我觉得两个脚本是可以改成一个 systemd service 的…
从我的 iPhone 发送,使用 Tapatalk
牵牛花大神
(牵牛花大神)
6
首先答复 4 楼的问题:
Hi,具体脚本看不到我理解,我现在想知道几件事:
- myscript 是怎么检测 Sybase 是否在运行的,通过进程?通过 PID 文件?通过 socket?
回答: 实现方式是 pronum=ps -ef | grep sybase | grep DBSVR | grep -v grep|wc -l
# 得出进程中包含数据库相关进程的数目
- 执行 closeSybase 后,你有没有加 wait?Systemd 是并发的… 看你的描述我感觉是 closeSybase 执行后就不管它,直接去取状态了。
回答:你说加 wait 的意思是指等待一段时间吗,我在代码中有 sleep 50 ,但实际发现无论 sleep 多久,哪怕是 sleep 600,sybase 运行状态始终是 true。
后来又添加了问题 1 中的判断 sybase 相关的进程是否存在的语句, 可打印的日志显示 sybase 仍然是运行的。
- Systemd 关机时服务的执行顺序跟开机是反的,你的 myscript 是在 ExecStart 里调用的还是在 ExecStop 里调用的?正常是 ExecStop 里。所以你的 myscript 脚本的 stop block 是怎么写的?不会写到 start block 里去了吧?因为 systemd 对 sysvinit 脚本的兼容是 start 对应 ExecStart,stop 对应 ExecStop,然后你的脚本只管关机,你觉得在 start 里执行就好。
回答:myscript 是在 start 代码块执行的,经过对比确认关机的时间和脚本打印日志的时间,myscript 脚本确实是在关机时启动的。
Sybase 是闭源的,不过我们可以用 mysql 之类的来模拟的。问题是能够得到解决的,但你的让我们能够模拟出来…
下面是牵牛花大神的回复:
资料参考:
zh.opensuse.org/index.php?title=openSUSE:Packaging_init_scripts&variant=zh-cn
第一步:
下面是启动的脚本 startMscript 内容,放在 /etc/init.d/ 目录下,
BEGIN INIT INFO
Provides: Pharbitis
Required-Start:
Should-Start: sybase
Required-Stop:
Should-Stop:
Default-Start: 0 6
Default-Stop: 1 2 3 5
Short-Description: Sound daemon with network support
Description: Starts esound server to allow remote access to sound
END INIT INFO
case “$1” in
start)
timeout 300 bash /opt/tools/myscript.sh
;;
stop)
;;
esac
下面是 myscript 脚本内容,放在 /opt/tools/ 目录下
#!/bin/bash
# 此处省略一些打印日志的代码 和其他辅助代码 , 仅列出调用 jar
# 这里使用 java 调用 closeSybase.sh 关闭 sybase 数据库。在 java 内部调用实现调用 closeSybase.sh,向该脚本传入密码参数
/opt/OSSJRE/linux/java -classpath XXX.jar com.oss.mainFrame "/opt/tools/closeSybase.sh"
sleep 50
pronum=ps -ef | grep sybase | grep DBSVR | grep -v grep|wc -l
# 得出进程中包含数据库相关进程的数目
# 判断 pronum 数目是否为 0,下面省略判断及打印日志部分代码
下面是 closeSybase.sh 脚本内容,放在 /opt/tools/ 目录下
. /opt/sybase/SYBASE.sh
cd /opt/sybase/OCS*/bin
bb=$(cat) # 由于当前脚本是用 -classpath 的形式调用的,变量 bb 用来接收 java 传进来的密码
isql -SDBSVR -Usa -P${bb} -zus_english -o/opt/isql_result.log<<EOF
shutdown SYB_BACKUP
go
shutdown
go
exit
EOF
cd /opt/oss/engr/tools/stopNMS_DB.sh_log/
echo " line${LINENO}] stopsinglesybase end of excute..">>${logfile}
#sleep 50
echo "`ps -ef | grep sybase | grep DBSVR | grep -v grep|wc -l`">>${logfile}
echo " now is checking the sybase status......">>${logfile}
isdbrun="false" # 此变量用于标记数据库运行状态
Line_Number=`ps -ef | grep sybase | grep DBSVR | grep -v grep|wc -l` # 得出进程中包含数据库相关进程的数目
if $Line_Number -eq 0 ]; then
# 数据库进程记录为 0,说明已经停止
echo " line${LINENO}] sybase has been shutdown ! ">>${logfile}
echo -e "echo " line${LINENO}] sybase has been shutdown ! ">>${logfile}
echo -e “\033[31m sybase has been shutdown ! \033[0m”>>${logfile}
else 33[31m sybase has been shutdown ! echo " line[${LINENO}] sybase has been shutdown ! “>>${logfile}
echo -e “\03331m sybase has been shutdown ! \0330m”>>${logfile}
else 330m”>>${logfile}
else
# 如果数据库没有完全停止,杀进程(sybase 数据库相关的进程)
pro1=ps -ef|grep RUN_DBSVR|grep -v grep | grep -v killall | awk '{print $3}'
kill -9 $pro1
pro2=ps -ef|grep -sDBSVR|grep -v grep | grep -v killall | awk '{print $3}'
kill -9 $pro2
pro3=ps -ef|grep RUN_DBSVR_back|grep -v grep | grep -v killall | awk '{print $3}'
kill -s 9 $pro3
pro4=ps -ef|grep -SDBSVR_back|grep -v grep | grep -v killall | awk '{print $3}'
kill -s 9 $pro4
#sleep 20
fi
第二步: :执行命令,添加 startMscript 脚本为关机启动项
chkconfig --add startMscript
第三步: : shutdown -r now
第四步: :SUSE 开机成功后,查看打印的日志文件,日志显示关机过程中 myscript 脚本调用 closeSybase.sh 脚本,并 sleep 50 秒后 ,判断 sybase 运行状态的结果 仍然是运行的。
为什么在 SUSE 系统里 手动直接 bash /opt/oss/myscript.sh 却可以成功停止 sybase,好迷乱啊
那我猜就是写到了 start block 里的原因了…正常应该写到 stop block 里…因为你的脚本只干了 stop…start/stop 的意思不是启动停止脚本本身,而是启动停止脚本对应的服务…所以 start 里面都是启动服务的东西,stop 里面都是停止服务的东西,具体的还要验证一下。有时候程序是运行了,但能跑不代表如预期的跑,摊手…
从我的 iPhone 发送,使用 Tapatalk
这是我的版本 /etc/init.d/sybase:
#!/bin/sh
### BEGIN INIT INFO
# Provides: sybase (注意这里的名字一定要写成 /etc/init.d 下面的那个名字,这里是 sybase,不能大写首字母,或者写成其它什么鬼)
# Required-Start:
# Should-Start:
# Required-Stop:
# Should-Stop:
# Default-Start: 0 6
# Default-Stop: 1 2 3 4 5
# Short-Description: Sybase daemon
# Description: Start Sybase daemon
### END INIT INFO
case "$1" in
start)
/home/marguerite/start.sh
;;
stop)
/home/marguerite/stop.sh
;;
esac
跟你的没什么不同,chkconfig -a sybase 之后(chkconfig -a 就会调用 insserv,所以你后面那步 insserv 是多余的),通过 sudo systemctl status sybase.service 能看到
● sybase.service - LSB: Sybase daemon
Loaded: loaded (/etc/init.d/sybase; bad; vendor preset: disabled)
Active: inactive (dead)
Docs: man:systemd-sysv-generator(8)
是被 systemd 管理。这是我的 /home/marguerite/start.sh
#!/bin/sh
echo "sybase start block runs" | systemd-cat -t sybase -p emerg
我的 /home/marguerite/stop.sh
#!/bin/sh
echo "sybase stop block runs" | systemd-cat -t sybase -p emerg
命令的意思是把某句话写到 systemd 的 journal 里,方便我确定运行了哪个脚本。
如果关机是运行的 start block 的话,journal 里就会有那句话,运行的 stop block 的话,里面就应该是另外一句。
sudo journalctl --since 22:57 | grep “sybase”
(困了,详情如何,且待下回分晓)
牵牛花大神
(牵牛花大神)
9
非常感谢 marguerite,今天在公司折腾了一天,同时搞两个需求,都是在空档时间切换着搞,环境来回搭建地折腾,好累。
看到你的回复真的很感动,我在其他论坛发布的帖子根本没有人回复,为 marguerite 的精神占赞。
明天到公司按照你的方法再搞一遍。多谢多谢
牵牛花大神
(牵牛花大神)
10
为何无法将 level 6 设置成 on 呢,经过实际运行,确认重启时会启动脚本的运行
虽说 level 6 没有设置成 on ,但关机,重启 SUSE 确实执行了脚本
我觉得你觉得脚本执行了一定是错觉。我昨晚关机再开好多次,journal 里既没有 start block 也没有 stop block,也就是说服务根本没在 halt 的时候跑。实际上证明脚本执行了的方法很简单,随便 echo 点什么,然后用 systemd-cat 输出到 journal,journal 里有你 echo 的东西就是脚本执行了。
我猜测你觉得脚本执行了是因为它被自动转换成 systemd service 后是在开机运行了你的 start block。
于是我又仔细看了一下,发现一开始就被你绕进去了。你对运行级别 runlevel 的理解不对…运行级别是“处在那个状态”的时候,不是“那个状态发生前”的时候,所以比如 0 halt 状态,这个时候系统是关机断电了,什么也执行不了,6 reboot 同理。
真正想要关机或重启前执行什么东西,应该跟普通脚本一样,运行级别的 Default-Start 是 3 5,Default-Stop 是 0 1 2 4 6。因为 0 1 2 4 6 几乎都是特殊状态,处在那种状态里基本什么都干不了。然后通过 Required-Start 和 Required-Stop 这些脚本 dependency 来实现关机或重启执行脚本的 stop block。
这个逻辑是设计好的,你只能跟着逻辑走,不能去创造自己的逻辑。这个逻辑就是,在运行级别 3 5 下,通过 Required-Start 在比如有网了之后启动 sshd,通过 Required-Stop 在没网之前就停止 sshd,所以我一直强调关机跟开机是反的。你这里最多只是需要一些特殊的服务来确定关机,类似于 systemd 里的 multiuser.target,这个查资料能找到 sysvinit 对应的。所以你想要在关机执行你写的那个 sysvinit 脚本的 start 部分,简单说就是不可能的,start 部分只能在开机执行。
所以你的问题不是那两个脚本,是你对 runlevel,sysvinit 和 systemd 的理解有点想当然。回头我写个例子出来吧。
你的脚本就算能执行我觉得也是相当随机的,因为它没有把自己的依赖关系理顺,最终关机了它肯定会被停止,但如果那个时候连根分区都卸载了,你肯定取不到进程因为没有 ps 命令之类的。没法解释更多,只能说非预期行为,因为我也不知道它究竟什么时候停止的。
从我的 iPhone 发送,使用 Tapatalk
最终能用的 /etc/init.d/sybase 在这里,主要就是改了 runlevel,加了 Default-Start 和 Default-Stop。
#!/bin/sh
### BEGIN INIT INFO
# Provides: sybase
# Required-Start: $remote_fs $syslog
# Should-Start:
# Required-Stop: $remote_fs $syslog
# Should-Stop:
# Default-Start: 3 4 5
# Default-Stop: 0 1 2 6
# Short-Description: Sybase daemon
# Description: Stop Sybase daemon and check database status
### END INIT INFO
case "$1" in
start)
;;
stop)
/opt/sybase/myscript.sh
;;
esac
开机,关机,重启都会运行,其中只要关机或重启都会调用 myscript.sh。开机调用的是 start block 所以什么都不做。
再具体的,你先这么改了再看。
另外建议用 systemd-cat -t sybase-daemon -p info/warning/emerg 写入 systemd journal,这样比较好调试。写自己的 $log 里对于业务是方便,但对于过程不方便,因为你不知道与此同时 systemd 在干嘛。写到一起就方便多了。
牵牛花大神
(牵牛花大神)
13
厉害,你说的对,我处从做这个需求时就搞不清楚运行级别的事情,寨主好厉害。
似乎明白了一些你强调的 start 和 stop 的意义。