我正在实现自定义 gitlab-runer 执行器。 Gitlab 发送多个脚本按顺序执行,并希望在同一个 shell 会话中执行它们。但是,我的包装脚本被执行了多次。 虽然我可以做到
bash -s <script_from_gitlab.sh
,但这将在
new环境中执行多个脚本。我希望保持像“bash 服务”一样以开放的输入和输出运行,运行命令,然后在命令完成时收集输出并显示它,同时保留环境。这与 python 中的 Jupiter 笔记本非常相似。 如何实现这样的“持久 bash 会话”并在该会话中执行 one
命令并以非交互式方式收集其输出? 我唯一的想法是通过 uuid 分隔输出:
#!/bin/bash
prepare() {
# runs a bash in the background waiting for commands
mkfifo /tmp/fifoin /tmp/fifoout
bash -s </tmp/fifoin >/tmp/fifoout &
echo $! > /tmp/bashpid
}
run() {
mark=d1c21272-4055-4cd4-a0d4-3462e7d29373
{
# executes script
cat "$1"
echo "$mark"
} > /tmp/fifoin &
while IFS= read -r line; do
if [[ "$line" == "$mark" ]]; then
break
fi
printf "%s\n" "$line"
done
}
cleanup() {
pid=$(</tmp/bashpid)
kill "$pid"
tail -f --pid "$pid"
}
# executed with arguments: "cleanup" "run thiscript" "run thatscript" "cleanup" in order
"$1" "$2"
但是,这感觉像是一种解决方法,尤其是通过“标记”来获取脚本是否完成执行。有其他解决方案吗?
在现实生活中,命令是由 Nomad 调度程序运行的。都是一样的,只是用
bash -s
执行
nomad exec <allocid> bash -s
。#!/bin/sh
input=/tmp/pipe-input
output=/tmp/pipe-output
# Wait for commands from pipe $input and send results to pipe $output
server(){
rm -f $input $output
mkfifo $input $output
while true; do
echo "Hello from server." >&2
eval "$(cat $input)" > $output
done
}
client(){
cat > $input; cat $output
}
# Send commands to server every second.
test-client(){
while sleep 1; do
client <<< 'echo $(date +%T) server hostname=$(hostname), server bash PID=$$'
done
}
"$@"
在一个窗口中运行
bash test.sh server
在另一个窗口中,运行
bash test.sh test-client
我认为
eval
的使用是“可以容忍的”,因为你可以控制要运行的命令。