Измените его на:
(cat; exec ps -o pid,args) << EOF
$(ps -o pid,ppid,args -H)
EOF
Посмотреть, что происходит.
С помощью bash
вы увидите:
$ bash./script
PID PPID COMMAND
428458 428451 /bin/zsh
976353 428458 bash./script
976354 976353 bash./script
976355 976354 ps -o pid,ppid,args -H
PID COMMAND
428458 /bin/zsh
976353 bash./script
976354 ps -o pid,args
$ ksh93u+m./script
PID PPID COMMAND
428458 428451 /bin/zsh
976559 428458 ksh93u+m./script
976560 976559 ps -o pid,ppid,args -H
PID COMMAND
428458 /bin/zsh
976559 ksh93u+m./script
976562 ps -o pid,args
Посмотрите, как в bash
, 976354 (дочерним элементом$$
)является тот, который разветвил дочерний процесс для запуска команды -, заменив ps
, а затем продолжил выполнение ps
, в то время как в ksh процесс, который запускал команду -, замененную ps
, был разветвлен основным процессом ksh ($$
), поэтому раньше.
pgrep -P "$$"
перечисляет дочерние процессы процесса, который запускал оболочку для интерпретации вашего сценария (, но никогда не перечисляет себя ). В bash это включает процесс, который в конечном итоге запустит ваш sqlplus
, потому что bash
делает это именно так.
Такой способ упрощает управление заданиями в интерактивных оболочках, так как вы можете поместить команду -замещенный процесс в группу процессов переднего плана, чтобы он также прерывался при нажатии Ctrl+C, и вы обнаружите, что кш93,при интерактивном запуске это также происходит, когда перенаправленная команда является внешней командой.
Но в случае ksh во время работы pgrep -P
нет другого потомка $$
, кроме того, который работает pgrep
. Тот, который будет запускать sqlplus
, будет запущен позже, поэтому вывод pgrep
будет пустым, и ваш sqlplus
жалуется на это define=
.
Если точка должна передать define=<pid>
в sqlplus
, где <pid>
— pid процесса, который будет выполнять sqlplus
, более надежным способом будет:
sh -c 'exec sqlplus -s / << EOF
define a=$$
define a
!ptree &a
EOF'
Где, поскольку мы используем exec
, мы знаем, что $$
в этом новом экземпляре sh
— это процесс, который будет выполнять sqlplus
.