如何以批处理模式可靠地检测 Bash 中的 stdin 管道?

如何以批处理模式可靠地检测 Bash 中的 stdin 管道?

我需要一种方法来测试当脚本以批处理模式运行时,Bash 脚本的输入是否已通过管道传输到标准输入。我以交互方式运行脚本时使用的方法(测试 [ -p /dev/stdin ])在批处理模式下失败。具体来说,它在 PBS 中失败,但在 SLURM 批处理队列中失败。我需要一种能够与 PBS 和 SLURM 交互工作(连接到终端)并以批处理模式工作的方法。

“-p /dev/stdin”测试在 PBS 批处理模式下产生意外结果。下面的测试显示,每当程序以批处理模式执行时,程序都会期望从管道到标准输入的数据,即使脚本没有创建这样的管道。这意味着 PBS 在批处理模式下使用 stdin 执行一些特殊操作(除了将其与终端断开连接之外)。无论出于何种原因,这种行为都违反了批处理作业的行为类似于以相同方式调用的交互式作业的前提。这种行为会导致我的脚本在 PBS 中以批处理模式崩溃。

在 SLURM 环境中执行的相同测试的行为符合预期,并且报告没有标准输入管道,除非用户创建了一个。

是否有一个可以在 PBS 和 SLURM 中交互工作的跨平台解决方案?如所附脚本所示,测试 [ ! -t 0 ] 也不是我需要的。

查理

cat > ~/inp_std.sh << 'EOF'
#!/bin/bash
if [ -p /dev/stdin ]; then
    printf "[ -p /dev/stdin ] is true\n"
else
    printf "[ -p /dev/stdin ] is false\n"
fi # !stdin
if [ ! -t 0 ]; then
    printf "[ ! -t 0 ] is true\n"
else
    printf "[ ! -t 0 ] is false\n"
fi # !stdin
EOF
chmod 755 ~/inp_std.sh
cat > ~/inp_std_tst.sh << 'EOF'
#!/bin/bash
echo foo > ~/foo
printf "No pipe, no re-direction: ~/inp_std.sh\n"
~/inp_std.sh
printf "Pipe to stdin:            echo hello | ~/inp_std.sh\n"
echo hello | ~/inp_std.sh
printf "Redirection to stdin:     ~/inp_std.sh < foo\n"
~/inp_std.sh < ~/foo
EOF
chmod 755 ~/inp_std_tst.sh
qsub -A CLI115 -V -l nodes=1 -l walltime=00:30:00 -N inp_std -j oe -m e -o ~/inp_std.out ~/inp_std_tst.sh
qsub -A arpae -l walltime=00:30:00 -l nodes=1 -N inp_std -q batch -j oe -m e -o ~/inp_std.out ~/inp_std_tst.sh
sbatch -A acme --nodes=1 --time=00:30:00 --partition=debug --job-name=inp_std --mail-type=END --output=${HOME}/inp_std.out ~/inp_std_tst.sh

PBS 结果:

zender@rhea-login4g:~$ more ~/inp_std.out
No pipe, no re-direction: ~/inp_std.sh
[ -p /dev/stdin ] is true
[ ! -t 0 ] is true
Pipe to stdin:            echo hello | ~/inp_std.sh
[ -p /dev/stdin ] is true
[ ! -t 0 ] is true
Redirection to stdin:     ~/inp_std.sh < foo
[ -p /dev/stdin ] is false
[ ! -t 0 ] is true

SLURM 的结果:

zender@edison05:~> more ~/inp_std.out
Running with ~/inp_std.sh:
[ -p /dev/stdin ] is false
[ ! -t 0 ] is true
Running with echo hello | ~/inp_std.sh:
[ -p /dev/stdin ] is true
[ ! -t 0 ] is true
Running with ~/inp_std.sh < foo:
[ -p /dev/stdin ] is false
[ ! -t 0 ] is true

请注意对于完全相同的脚本,PBS 结果的第一行与 SLURM 结果有何不同。

相关内容