Greg's Wiki有一个非常简单的例子,说明如何让服务器运行s.t.如果它退出,它会立即重新启动:
#!/bin/sh
while :; do
/my/game/server -foo -bar -baz >> /var/log/mygameserver 2>&1
done
但是你想让N服务器保持运行的位置,s.t。如果一个失败,所有应该重新启动? http://wiki.bash-hackers.org/scripting/bashchanges说bash 4.3会让我做
while :; do
server1 & p1=$!
server2 & p2=$!
wait -n $p1 $p2 # wait until at least one exits
kill $p1 $p2
done
但4.3仍处于alpha状态,有没有办法用旧系统执行此操作?
答案 0 :(得分:0)
以下是我提出的方法,基于Greg's Wiki和#bash在irc.freenode.net上的一些帮助:
#!/bin/bash
trap 'rm -f manager; kill 0' EXIT
mkfifo manager
declare -A pids
restart () {
# assuming your servers/daemons are programs "a" and "b"
[[ -n ${pids[a]} ]] && kill "${pids[a]}"
[[ -n ${pids[b]} ]] && kill "${pids[b]}"
run_and_tell manager a & pids[a]=$!
run_and_tell manager b & pids[b]=$!
}
restart
while :; do
read < manager
restart
done
和run_and_tell:
#!/bin/bash
trap 'kill $pid' EXIT
manager=$1
prog=$2
$prog & pid=$!
wait $pid
echo >"$manager"
不如bash 4.3版本好,但似乎有效(例如在run_and_tell中使用“sleep 9999”进行测试)。令人烦恼的是,我必须在跑步者中trap 'kill $pid' EXIT
,而且似乎我必须在$ prog中做同样的事情,以确保它的父母被杀时被杀死。
这是一个替代版本,通过将run_and_tell放在自己的process group中来避免陷阱:
#!/bin/bash
# The trap now needs to kill all created process groups:
trap 'rm -f manager; kill 0; kill ${pids[a]} ${pids[b]}' EXIT
mkfifo manager
declare -A pids
restart () {
# assuming servers/daemons are programs "a" and "b":
[[ -n ${pids[a]} ]] && kill -TERM -"${pids[a]}"
[[ -n ${pids[b]} ]] && kill -TERM -"${pids[b]}"
setsid ./run_and_tell manager a & pids[a]=$!
setsid ./run_and_tell manager b & pids[b]=$!
}
restart
while :; do
read < manager
restart
done
和run_and_tell变为:
#!/bin/bash
manager=$1
prog=$2
$prog
echo >"$manager"
答案 1 :(得分:0)
最简单的方法是每隔一段时间手动检查一次:
#!/bin/bash
function check_if_all_active {
local p
for p in "$@"; do
kill -s 0 "$p" &>/dev/null || return 1
done
return 0
}
while :; do
pids=()
server1 & pids+=("$!")
server2 & pids+=("$!")
while check_if_all_active "${pids[@]}"; do
sleep 1s ## Can be longer.
done
kill -s SIGTERM "${pids[@]}" &>/dev/null
done
您还可以考虑其他信号来停止您的流程,例如SIGHUP或SIGABRT。