2

我有一个java program我正在从标准输入读取

BufferedInputStream bis = new BufferedInputStream(System.in);
byte[] b = new byte[1];
int cmd = bis.read(b);
System.out.println("Read command: " + new String(b));

和一个shell script启动停止这个程序

'start')
if [ -p myfifo ]; then
    rm myfifo
    rm myfifo-cat-pid
fi
mkfifo myfifo
cat > myfifo &
echo $! > myfifo-cat-pid
java -jar lib/myJar.jar >/dev/null 2>&1 0<myfifo &
echo `date +%D-%T` $! >> process.pid
echo "Started process: "$!
;;

'stop')
echo 0 > myfifo
echo "Stopped process: "
rm myfifo
;;

当我在开始时一一运行命令时,程序会一直等到我在 fifo 上回显。但是当我从 .sh 文件运行它时,它会立即从标准输入中读取。不明白如果直接在命令提示符下运行命令与我创建一个 .sh 文件然后运行它有什么区别

4

1 回答 1

1

区别不在于Java侧面,而是在于您的 shell 在启动脚本时处理作业控制的方式不同。来自man bash

JOB CONTROL
   Job  control  refers  to  the ability to selectively stop (suspend) the
   execution of processes and continue (resume) their execution at a later
   point.   A  user  typically  employs  this  facility via an interactive
   interface supplied jointly by the operating  system  kernel's  terminal
   driver and bash.

正如这里所解释的,默认情况下,脚本中的作业控制是禁用的。

cat > myfifo &交互式 shell 中执行时,它保持在“已停止”模式,等待再次置于前台(使用fg)。相反,当在脚本中启动时,作业控制被禁用,因此,一旦cat尝试从(分离的)终端读取,它就存在,关闭管道(并且您的Java进程读取EOF)。

如果您set -m在 shell 脚本的顶部使用(因此启用强制作业控制),您应该会看到一致的行为。

set [+abefhkmnptuvxBCEHPT] [+o option-name] [arg ...]
  -m      Monitor mode.  Job control is enabled.  This option is on by
          default for interactive shells on systems  that  support  it
          (see JOB CONTROL above).  Background processes run in a sep‐
          arate process group and a line containing their exit  status
          is printed upon their completion.
于 2012-07-30T07:33:51.023 回答