科恩脚本:
#!/bin/ksh
sqlplus -s / << EOF
define a=$(pgrep -P $$)
define a
!ptree &a
EOF
VS
重击脚本:
#!/bin/bash
sqlplus -s / << EOF
define a=$(pgrep -P $$)
define a
!ptree &a
EOF
Korn shell 输出(未按预期工作):
$ /tmp/testsql.ksh
SP2-0137: DEFINE requires a value following equal sign
SP2-0135: symbol a is UNDEFINED
Enter value for a:
SP2-0546: User requested Interrupt or EOF detected.
Bash shell 输出(按预期工作):
$ /tmp/testsql.bash
DEFINE A = "2713" (CHAR)
710 /usr/lib/ssh/sshd
9574 /usr/lib/ssh/sshd -R
9578 /usr/lib/ssh/sshd -R
.
.
.
2712 /bin/bash /tmp/testsql.sh
2713 sqlplus -s /
2717 ptree 2713
有什么想法可以让这个在 ksh 脚本中工作吗?
答案1
将其更改为:
(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 "$$"
列出执行 shell 来解释脚本的进程的子进程(但从不列出其自身)。在 bash 中,这恰好包括最终将运行你的进程,sqlplus
因为bash
恰好就是这样做的。
这样做可以使交互式 shell 中的作业控制更容易,因为您可以将命令替换的进程放在前台进程组中,因此当您按 Ctrl+C 时它也会被中断,并且您会发现 ksh93 在交互运行时当重定向命令是外部命令时也会执行此操作。
但就 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
。