栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

需要Linux bash内置exec命令行为的解释

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

需要Linux bash内置exec命令行为的解释

在这种情况下,您可以

exec
使用管道。为了执行一系列流水线命令,外壳程序必须首先进行分叉,并创建一个子外壳程序。(具体来说,它必须先创建管道,然后创建派生,以便所有在管道“左侧”运行的东西都可以将其输出发送到管道“右侧”的任何内容。)

要查看实际上这是正在发生的情况,请比较:

{ ls; echo this too; } | cat

与:

{ exec ls; echo this too; } | cat

前者运行时

ls
不会离开子外壳,因此该子外壳仍然可以运行
echo
。后者
ls
通过保留子外壳运行,因此不再在那里做子外壳
echo
,并且
thistoo
不进行打印。

(大括号的使用

{ cmd1; cmd2; }
通常会抑制您在圆括号中得到的子壳分叉动作
(cmd1;cmd2)
,但是对于管道,该分叉实际上是“强制的”。)

仅当单词后面没有“什么可以运行”时,才进行当前shell的重定向

exec
。因此,例如
exec >stdout 4<input5>>append
修改当前的shell,但是
exec foo >stdout 4<input 5>>append
尝试执行exec command
foo
。[注意:这并非严格准确;见附录。]

有趣的是,在交互式外壳程序中,

exec foo >output
由于没有命令而失败后
foo
,外壳程序仍然存在,但stdout仍重定向到file
output
。(您可以使用恢复
exec >/dev/tty
。在脚本中,无法
exec foo
终止脚本。)


在@ Pumbaa80的提示下,这里的内容更具说明性:

#! /bin/bashshopt -s execfailexec ls | cat -Eecho this goes to stdoutecho this goes to stderr 1>&2

(注意:

cat -E
从我的平时简化了下来
cat-vET
,这是我方便使用的“让我以可识别的方式查看非打印字符”)。运行此脚本时,来自的输出
ls
cat-E
应用(在Linux上,行尾显示为$符号),但是发送到stdout和stderr的输出(在其余两行上) 重定向。更改
| cat -E
>out
,在脚本运行后,观察文件的内容
out
:最后两个
echo
不存在。

现在将更

ls
改为
foo
(或将找不到的其他命令),然后再次运行脚本。这次的输出是:

$ ./demo.sh./demo.sh: line 3: exec: foo: not foundthis goes to stderr

out
现在该文件具有第一
echo
行生成的内容。

这使得

exec
“真正做到的” 事情变得尽可能明显(但不再那么明显,因为爱因斯坦没有提出:-))。

通常,当外壳进入执行“简单的命令”(见手册页的精确定义,但此明确排除在“管道”的命令),它准备与指定的任何I /
O重定向操作

<
>
等打开所需的文件。然后,shell调用
fork
(或一些等效但效率更高的变体,例如
vfork
clone
取决于底层操作系统,配置等),并在子进程中重新排列打开的文件描述符(使用
dup2
调用或等效方法)以实现所需的最终排列:
>out
将打开描述符移动到fd 1(stdout),同时
6> out
将打开描述符移动到fd 6。

exec
但是,如果指定关键字,则外壳程序将取消执行该
fork
步骤。它照常进行所有文件打开和文件描述符重新排列,但是这次, 它影响所有后续命令
。最后,在完成所有重定向后
execve()
,如果存在命令,shell尝试(从系统调用的角度)尝试命令。如果没有命令,或者
execve()
调用失败

并且shell应该继续运行(是交互式的或已设置
execfail
),则shell士兵会继续前进。如果
execve()
成功,则该外壳不再存在,已被新命令替换。如果
execfail
未设置,并且外壳不是交互式的,则外壳退出。

(还增加了

command_not_found_handle
shell函数的复杂性:bash
exec
似乎根据测试结果禁止运行它。
exec
通常,该关键字使shell不会查看其自身的函数,即,如果您有shell函数f,则
f
作为a
运行简单命令会运行shell函数,就像
(f)
在子shell中运行壳函数一样,但是运行会
(exec f)
跳过它。)


至于为什么要

ls>out1ls>out2
创建两个文件(带或不带
exec
),这很简单:shell打开每个重定向,然后使用它们
dup2
来移动文件描述符。如果您有两个普通的
>
重定向,则外壳程序将同时打开两个外壳,将第一个重定向到fd
1(stdout),然后将第二个重定向到fd 1(stdout),在此过程中关闭第一个。最终,它运行了
ls ls
,因为删除了`>out1

out2

。只要没有名为
ls
的文件,该
ls`命令就会向stderr投诉,而不会向stdout写入任何内容。



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/409056.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号