2009-10-04 68 views
4

我在/etc/init.d目录 甲骨文关机脚本的“停止”命令,它的作用:在超过指定时间的bash中杀死进程?

su oracle -c "lsnrctl stop >/dev/null" 
su oracle -c "sqlplus sys/passwd as sysdba @/usr/local/PLATEX/scripts/orastop.sql >/dev/null" 

.. 问题是,当LSNRCTL或sqlplus的是反应迟钝 - 在这种情况下,该“停止”脚本永远不会结束,服务器无法关闭。唯一的方法 - 就是“杀死-9”。

我想重写脚本,以便5分钟后(例如)如果命令没有完成 - 它应该被终止。

我该如何做到这一点?你能举个例子吗? 我在Linux RHEL 5.1 + bash下。

+0

我不会写在bash;我会寻找一个能为你做到的程序。我们有一个内部工具(不幸的是,这是封闭的源代码)。 – JesperE

+0

Bash难以做到吗?你为什么喜欢你自己的工具? 我可以写一个perl,java工具,但我认为在bash中做更多的本地和简单? – zmische

+0

嗯,在你可以直接访问'waitpid'的地方做某事,它实际上支持超时值。不过,Bash也很好,过去我已经使用它(字面意思就是为了这个目的)。 (前雇主,没有继续访问脚本,自那时起我已经睡了足够多的时间,我不太可能记得那些域特定和有用的)。 –

回答

9

如果能够使用第三方工具,我会充分利用第三方的一个,预先写好的助手,你可以从你的脚本(doalarmtimeout都由the BashFAQ entry on the subject提到)调用。

如果写这样的事我不使用这样的工具,我可能会做一些这样的:

function try_proper_shutdown() { 
    su oracle -c "lsnrctl stop >/dev/null" 
    su oracle -c "sqlplus sys/passwd as sysdba @/usr/local/PLATEX/scripts/orastop.sql >/dev/null" 
} 

function resort_to_harsh_shutdown() { 
    for progname in ora_this ora_that ; do 
    killall -9 $progname 
    done 
    # also need to do a bunch of cleanup with ipcs/ipcrm here 
} 

# here's where we start the proper shutdown approach in the background 
try_proper_shutdown & 
child_pid=$! 

# rather than keeping a counter, we check against the actual clock each cycle 
# this prevents the script from running too long if it gets delayed somewhere 
# other than sleep (or if the sleep commands don't actually sleep only the 
# requested time -- they don't guarantee that they will). 
end_time=$(($(date '+%s') + (60 * 5))) 
while (($(date '+%s') < end_time)); do 
    if kill -0 $child_pid 2>/dev/null; then 
    exit 0 
    fi 
    sleep 1 
done 

# okay, we timed out; stop the background process that's trying to shut down nicely 
# (note that alone, this won't necessarily kill its children, just the subshell we 
# forked off) and then make things happen.  
kill $child_pid 
resort_to_harsh_shutdown 
+0

AFAIR我们可以在bash中使用WAITPID? 那么while循环中的waitpid + WHOHANG选项怎么样呢?这个选项测量自exec和终止以来的时间? (我认为,而不是“如果[[!-e/proc/$ child_pid]];然后”施工?) – zmische

+0

你记得不正确; bash的wait构造接受一个pid作为参数,但没有别的(没有超时,所以你失去了实际的waitpid系统调用的大部分功能)。 –

+0

......但是,如果我们能做到这一点,那么它就会少得多。 :) –

6

哇,这是一个复杂的解决方案。这里更容易一些。您可以跟踪PID并在稍后停用。

my command & #where my command is the command you want to run and the & sign backgrounds it. 
PID=$! #PID = last run command. 
sleep 120 && doProperShutdown || kill $PID #sleep for 120 seconds and kill the process properly, if that fails, then kill it manually.. this can be backgrounded too.