我是 bash 脚本的新手,想问一下实现以下目标的最佳/最简单方法是什么:
- 并行运行命令(例如运行 Nodejs Web 应用程序);命令的输出应像往常一样写入控制台
- 等到输出中出现特定字符串(例如“DB已初始化”)
- 然后运行另一个命令(例如创建一些数据库数据的命令)
- 然后等待 1. 中的命令结束
这是我当前的脚本,用于等待sleep
,但当然这只是一个解决方法:
# parallel command
npm run start &
# wait for specific output
sleep 15s
# do something
node_modules/.bin/knex seed:run
# wait for parallel command to exit
wait
我找到了一个类似的问题但我认为并行执行的命令的输出不会打印到控制台。
背景:该脚本是基于nodejs镜像的alpine变体的docker镜像的入口点。
答案1
实现这一目标的可能方法之一:
npm run start |
tee /dev/tty | {
grep -q "DB initialized" && node_modules/.bin/knex seed:run
cat >/dev/null
}
tee /dev/tty
复制 的npm
输出并将其发送到终端和管道中后续的命令。
grep -q
在第一场比赛时静默退出,0
其状态为;这将触发“AND”列表中的下一个命令 ( node_modules/.bin/knex seed:run
)。
cat /dev/null
是否只是为了保持管道打开:grep -q
退出会导致tee
在尝试向管道写入更多数据并依次退出时收到 SIGPIPE 信号。这cat
可以防止从管道读取直到npm
退出tee
。
无需npm
异步运行:管道的所有组件同时运行,您唯一要确保的是在较慢的组件完成之前它们都不会退出。
请注意,/dev/tty
如果此代码段在没有控制终端的进程上下文中运行,则可能不可用。假设标准流也可以/dev/fd/n
在您的系统上以表单访问,另一种选择是:
npm run start | {
tee /dev/fd/9 | {
grep -q "DB initialized" && node_modules/.bin/knex seed:run
cat >/dev/null
}
} 9>&1
文件描述符9
(任意选择)被创建为整个管道的标准输出连接到的文件的副本,使其可用于/dev/fd/9
外部{ ... }
列表中的任何命令。