我有这个脚本来执行应用程序,并控制启动时的任何错误,但需要对此执行更好的控制,并使用“网络名称空间”在ID为“ controlnet”的netns上重定向此应用程序。最后一行脚本运行正常,但是我重定向到黑屏,退出后我可以看到应用程序正在运行,但未在“ controlnet”命名空间上初始化。
如果手动执行所有步骤,则一切正常:
sudo ip netns exec controlnet sudo -u $USER -i
cd /home/app-folder/
./hlds_run -game cstrike -pidfile ogp_game_startup.pid +map de_dust +ip 1.2.3.4 +port 27015 +maxplayers 12
如何将这些行添加到完整的bash中?
使用的脚本:
#!/bin/bash
function startServer(){
NUMSECONDS=`expr $(date +%s)`
until ./hlds_run -game cstrike -pidfile ogp_game_startup.pid +map de_dust +ip 1.2.3.4 +port 27015 +maxplayers 14 ; do
let DIFF=(`date +%s` - "$NUMSECONDS")
if [ "$DIFF" -gt 15 ]; then
NUMSECONDS=`expr $(date +%s)`
echo "Server './hlds_run -game cstrike -pidfile ogp_game_startup.pid +map de_dust +ip 1.2.3.4 +port 27015 +maxplayers 12 ' crashed with exit code $?. Respawning..." >&2
fi
sleep 3
done
let DIFF=(`date +%s` - "$NUMSECONDS")
if [ ! -e "SERVER_STOPPED" ] && [ "$DIFF" -gt 15 ]; then
startServer
fi
}
sudo ip netns exec controlnet sudo -u myuser -i && cd /home/ && startServer
答案 0 :(得分:0)
此处的关键问题是sudo -u myuser -i
开始一个新的Shell会话。在外壳会话中 之前,不会运行其他命令,例如cd /home
。相反,它们在Shell会话后运行。
因此,您需要将startServer 移到 sudo
命令中,而不是在 sudo
命令之后运行它。
一种方法是通过heredoc传递应在sudo
下运行的代码:
#!/bin/bash
sudo ip netns exec controlnet sudo -u myuser bash -s <<'EOF'
startServer() {
local endTime startTime retval
while :; do
startTime=$SECONDS
./hlds_run -game cstrike -pidfile ogp_game_startup.pid +map de_dust +ip 1.2.3.4 +port 27015 +maxplayers 14; retval=$?
endTime=$SECONDS
if (( (endTime - startTime) > 15 )); then
echo "Server crashed with exit code $retval. Respawning..." >&2
else
echo "Server exited with status $retval after less than 15 seconds" >&2
echo " not attempting to respawn" >&2
return "$retval"
fi
sleep 3
done
}
cd /home/ || exit
startServer
EOF
这里重要的是,我们不再运行sudo -i
,并期望脚本的其余部分被隐式地馈入升级的shell中。相反,我们正在运行bash -s
(从stdin读取脚本文本来运行),并传递startServer
函数的文本和在该stdin流中调用该函数的命令。