庆典和ksh之间的子shell diffferences [英] Sub-shell diffferences between bash and ksh
问题描述
我始终认为,一个子shell不是一个子进程,但另一
外壳环境中相同的处理。
I always believed that a sub-shell was not a child process, but another shell environment in the same process.
我使用了一组基本的内置插件的:
I use a basic set of built-ins:
(echo "Hello";read)
在另一个终端:
ps -t pts/0
PID TTY TIME CMD
20104 pts/0 00:00:00 ksh
所以,在没有kornShell子进程(KSH)。
So, no child process in kornShell (ksh).
输入bash中,它似乎表现不同,给予同样的命令:
Enter bash, it appears to behave differently, given the same command:
PID TTY TIME CMD
3458 pts/0 00:00:00 bash
20067 pts/0 00:00:00 bash
所以,在bash子进程。结果
从阅读对于bash的man页面,很明显,为一个子shell创建了另一个进程,
然而,假货$$,这是sneeky。
So, a child process in bash.
From reading the man pages for bash, it is obvious that another process is created for a sub-shell,
however it fakes $$, which is sneeky.
这是Bash和ksh之间的这种差异预期,还是我读症状不正确?
Is this difference between bash and ksh expected, or am I reading the symptoms incorrectly?
编辑:附加信息:
运行 strace的-f
在bash和ksh的Linux上显示的bash调用克隆
两次样本命令(它不叫叉
)。所以庆典可能会使用线程(我试过 ltrace
,但它的核心倾倒!)。
KornShell呼吁既不叉
,的vfork
,也不克隆
。
additional information:
Running strace -f
on bash and ksh on Linux shows that bash calls clone
twice for the sample command (it does not call fork
). So bash might be using threads (I tried ltrace
but it core dumped!).
KornShell calls neither fork
, vfork
, nor clone
.
推荐答案
ksh93的工作异常辛苦,避免子shell。部分原因是stdio的和广泛使用的了sfio 的避免这允许内建直接沟通。另一个原因是KSH理论上可以有这么多的内置命令。如果用 SHOPT_CMDLIB_DIR
建成,所有的cmdlib建宏包含并默认启用。我不能给一个COM prehensive哪里避免子shell地方名单,但它通常是在仅使用内建的情况,并在没有重定向。
ksh93 works unusually hard to avoid subshells. Part of the reason is the avoidance of stdio and extensive use of sfio which allows builtins to communicate directly. Another reason is ksh can in theory have so many builtins. If built with SHOPT_CMDLIB_DIR
, all of the cmdlib builtins are included and enabled by default. I can't give a comprehensive list of places where subshells are avoided, but it's typically in situations where only builtins are used, and where there are no redirects.
#!/usr/bin/env ksh
# doCompat arr
# "arr" is an indexed array name to be assigned an index corresponding to the detected shell.
# 0 = Bash, 1 = Ksh93, 2 = mksh
function doCompat {
${1:+:} return 1
if [[ ${BASH_VERSION+_} ]]; then
shopt -s lastpipe extglob
eval "${1}[0]="
else
case "${BASH_VERSINFO[*]-${!KSH_VERSION}}" in
.sh.version)
nameref v=$1
v[1]=
if builtin pids; then
function BASHPID.get { .sh.value=$(pids -f '%(pid)d'); }
elif [[ -r /proc/self/stat ]]; then
function BASHPID.get { read -r .sh.value _ </proc/self/stat; }
else
function BASHPID.get { .sh.value=$(exec sh -c 'echo $PPID'); }
fi 2>/dev/null
;;
KSH_VERSION)
nameref "_${1}=$1"
eval "_${1}[2]="
;&
*)
if [[ ! ${BASHPID+_} ]]; then
echo 'BASHPID requires Bash, ksh93, or mksh >= R41' >&2
return 1
fi
esac
fi
}
function main {
typeset -a myShell
doCompat myShell || exit 1 # stripped-down compat function.
typeset x
print -v .sh.version
x=$(print -nv BASHPID; print -nr " $$"); print -r "$x" # comsubs are free for builtins with no redirections
_=$({ print -nv BASHPID; print -r " $$"; } >&2) # but not with a redirect
_=$({ printf '%s ' "$BASHPID" $$; } >&2); echo # nor for expansions with a redirect
_=$(printf '%s ' "$BASHPID" $$ >&2); echo # but if expansions aren't redirected, they occur in the same process.
_=${ { print -nv BASHPID; print -r " $$"; } >&2; } # However, ${ ;} is always subshell-free (obviously).
( printf '%s ' "$BASHPID" $$ ); echo # Basically the same rules apply to ( )
read -r x _ <<<$(</proc/self/stat); print -r "$x $$" # These are free in {{m,}k,z}sh. Only Bash forks for this.
printf '%s ' "$BASHPID" $$ | cat # Sadly, pipes always fork. It isn't possible to precisely mimic "printf -v".
echo
} 2>&1
main "$@"
出:
Version AJM 93v- 2013-02-22
31732 31732
31735 31732
31736 31732
31732 31732
31732 31732
31732 31732
31732 31732
31738 31732
这一切的内部I / O处理的另一个后果整齐一些缓冲的问题走开。下面是读线, T恤
和头
建宏(不以任何其他shell试试这个)一个有趣的例子。
Another neat consequence of all this internal I/O handling is some buffering issues just go away. Here's a funny example of reading lines with tee
and head
builtins (don't try this in any other shell).
$ ksh -s <<\EOF
integer -a x
builtin head tee
printf %s\\n {1..10} |
while head -n 1 | [[ ${ { x+=("$(tee /dev/fd/{3,4})"); } 3>&1; } ]] 4>&1; do
print -r -- "${x[@]}"
done
EOF
1
0 1
2
0 1 2
3
0 1 2 3
4
0 1 2 3 4
5
0 1 2 3 4 5
6
0 1 2 3 4 5 6
7
0 1 2 3 4 5 6 7
8
0 1 2 3 4 5 6 7 8
9
0 1 2 3 4 5 6 7 8 9
10
0 1 2 3 4 5 6 7 8 9 10
这篇关于庆典和ksh之间的子shell diffferences的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!