在后台执行 bash shell 接受参数和 运行 的脚本

Executing bash shell script accepting argument and running in background

我写了一个 shell 脚本 run.sh 来根据用户的输入触发一些任务

#!/bin/bash

echo "Please choose mode [1-3]: "
read MODE

case $MODE in

  1)
    echo -n "Enter iteration: "
    read TIME
    echo "Start Updating ..."
    task 1 && task 2 && task 3  
    ;;

  2)
    echo -n "Enter Seed Value: "
    read SEED
    echo "Start Updating ..."
    task 4
    task 5
    ;;

  3)
    echo -n "Enter regression minimum value: "
    read MIN
    echo "Start Updating ..."
    task 6
    ;;

  *)
    echo -n "Unknown option - Exit"
    ;;
esac

任务 1,2 ... 6 是 php 脚本,与 运行 类似 /usr/bin/php task1.php $TIME,并以 $TIME 作为 php 脚本等的参数。 ..

当我输入 bash run.sh 时,脚本 运行 没问题,但由于任务 1-6 需要很长时间才能完成,我想要一个选项 运行 在后台运行脚本我断开与终端的连接。但是,如果我 运行 使用 bash run.sh & 的脚本,我会遇到这样的错误:

Please choose mode [1-3]: 2
-bash: 2: command not found

[5]+  Stopped                 bash run.sh

似乎 bash 将我的输入 2 解释为不对应于 read MODE 而不是 bash run.sh 2 的参数,这会导致错误。我无法更改脚本,使任务 1-6 在后台 运行,如 task 1 & task 2 & 等,因为任务 2 只能在任务 1 完成后开始 运行ning .

我怎样才能完成我想做的事情?

您可以 运行 在后台按顺序执行所有这些任务 subshell

( task 1; task 2; task 3 ) &

试试这个:

( echo "One"; sleep 1; echo "Two"; sleep 2; echo "Three"; sleep 3; echo "Done" ) &

你也可以做得更多 script-looking:

(
echo "One"
sleep 1
echo "Two"
sleep 2
echo "Three"
sleep 3
echo "Done"
) &

随意使用有用的 envar $BASH_SUBSHELL

( echo $BASH_SUBSHELL; ( echo $BASH_SUBSHELL ) )

简短回答:运行在后台运行交互式程序(/脚本)实际上不起作用;如果您断开与终端的连接,它的工作效果会更差。您应该重写脚本,这样它就不需要用户输入 运行s.

长答案:当您 运行 在后台运行脚本时,会发生这种情况。请注意,事件的确切顺序可能会有所不同,因为后台脚本和前台交互 shell 同时 运行 正在“竞速”完成任务。

  1. 您在后台启动脚本 bash run.sh &
  2. 您的交互式 shell 会立即为您的下一个命令做好准备,因此它会将您常用的命令提示符打印到终端。
  3. 您的脚本向终端打印 提示(“请选择模式 [1-3]:”)。
  4. 您的交互式 shell 从终端读取下一个命令。因为脚本的提示是第二个打印的,所以看起来您正在向它发送输入,但实际上最近的提示与哪个程序正在接收您的输入之间没有任何联系。
  5. 您的交互式 shell 尝试 运行 您的输入(“2”)作为命令,但失败了。
  6. 您的 shell 脚本终于有机会从终端 read...但是它在后台,所以不允许这样做。相反,它被挂起,并打印一条“已停止”消息。来自 bash man page,“作业控制”部分:

Background processes which attempt to read from (write to when stty tostop is in effect) the terminal are sent a SIGTTIN (SIGTTOU) signal by the kernel's terminal driver, which, unless caught, suspends the process.

此时,如果你想继续脚本并告诉它做什么,你需要将它移到前台(例如使用 fg)命令。这会否定这里的观点。此外,它的提示(“请选择模式 [1-3]:”)不会重复,因为 echo 命令在后台成功完成。

解决方案:基本上,将脚本写入 non-interactively 运行 任务的必要顺序。 @Lenna 给出了例子;听从她的建议。