我正在学习exec
命令。我知道exec
命令会替换启动它的进程。因此无法返回到被exec
命令替换的进程。
可以说,其目的是使进程无法返回到启动它的那个进程。
但是,将类似的东西exec
作为命令还有什么其他用途呢?
答案1
该 exec
命令用指定的命令替换当前 shell 进程。通常,运行命令时会生成(分叉)一个新进程。该exec
命令不会生成新进程。相反,当前进程会被新命令覆盖。换句话说,该exec
命令代替当前 shell 执行,而不会创建新进程。
exec 命令有三种最常见的用途:
1. 工艺流程的更换
示例 1:
如果你打开一个新的bash
shell
$ bash
看起来pstree
像
─gnome 终端 ═─bash───bash───pstree
之前的bash
shell 仍然存在,而你获得了一个新的bash
shell。而如果你打开一个新的 bash shell,
$ exec bash
演出pstree
─gnome 终端 ═─bash───pstree
这里旧的bash
被新的替换了。在一个命令中退出多重登录特别有用。它更加安全并且消除了错误地离开终端的可能性。看使用一个命令退出 root 和用户
示例 2:您可以打开一个文件
$ exec vi filename.txt
退出时vi
无需单独关闭终端,因为 shell 已被替换。关闭 vi 后,终端也会关闭。
2. Shell 脚本中文件描述符重定向的方法
该exec
命令还可以用于在 shell 脚本中动态打开、关闭和复制文件描述符。这允许将 STDIN、STDERR、STDOUT 和其他文件描述符重定向到 shell 脚本内的各种文件,而不是命令调用字符串。如果您未指定命令或参数,则可以指定重定向符号和文件描述符来执行这些功能。
假设你有一个 shell 脚本script.sh
,你想要一个日志文件script.log
,你可以exec
使用
LOG=/path/to/script.log
exec 1>>$LOG
exec 2>&1
相当于
./script &>> /path/to/script.log
./script >> /path/to/script.log 2>&1
3. 使用 exec 命令创建进程的各个阶段
您还可以使用 exec 命令创建一组 shell 脚本,这些脚本像进程的各个阶段一样按顺序执行。每次需要将控制权转移到下一个脚本时,您无需生成新进程,只需执行 exec 命令即可。
在这种情况下,每个阶段的最后一条语句应该是exec
调用下一阶段的命令。
看exec
shell 脚本中命令的用法了解更多信息。
笔记:以上部分摘自这。
答案2
在包装脚本中
exec
主要用于包装脚本。
如果要在执行主程序之前修改程序的环境,通常会编写一个脚本,并在脚本末尾启动主程序。但此时脚本无需保留在内存中。因此,在这些exec
情况下使用,以便主程序可以替换母脚本。
下面是一个实际的例子。它的mate-terminal.wrapper
脚本随 mate-terminal 一起提供。它mate-terminal
通过检查用户的环境来启动一些额外的参数。
#!/usr/bin/perl -w
my $login=0;
while ($opt = shift(@ARGV))
{
if ($opt eq '-display')
{
$ENV{'DISPLAY'} = shift(@ARGV);
}
elsif ($opt eq '-name')
{
$arg = shift(@ARGV);
push(@args, "--window-with-profile=$arg");
}
elsif ($opt eq '-n')
{
# Accept but ignore
print STDERR "$0: to set an icon, please use -name <profile> and set a profile icon\n"
}
elsif ($opt eq '-T' || $opt eq '-title')
{
push(@args, '-t', shift(@ARGV));
}
elsif ($opt eq '-ls')
{
$login = 1;
}
elsif ($opt eq '+ls')
{
$login = 0;
}
elsif ($opt eq '-geometry')
{
$arg = shift(@ARGV);
push(@args, "--geometry=$arg");
}
elsif ($opt eq '-fn')
{
$arg = shift(@ARGV);
push(@args, "--font=$arg");
}
elsif ($opt eq '-fg')
{
$arg = shift(@ARGV);
push(@args, "--foreground=$arg");
}
elsif ($opt eq '-bg')
{
$arg = shift(@ARGV);
push(@args, "--background=$arg");
}
elsif ($opt eq '-tn')
{
$arg = shift(@ARGV);
push(@args, "--termname=$arg");
}
elsif ($opt eq '-e')
{
$arg = shift(@ARGV);
if (@ARGV)
{
push(@args, '-x', $arg, @ARGV);
last;
}
else
{
push(@args, '-e', $arg);
}
last;
}
elsif ($opt eq '-h' || $opt eq '--help')
{
push(@args, '--help');
}
}
if ($login == 1)
{
@args = ('--login', @args);
}
exec('mate-terminal',@args);
这里要注意的一点是,有一个exec
调用,它在内存中替换了这个脚本。
以下是 Unix 和 Linux StackExchange 网站上回答的类似问题 -https://unix.stackexchange.com/q/270929/19288
重定向文件描述符
的另一个常见用途exec
是重定向文件描述符。stdin
,stdout
,stderr
可以使用 exec 重定向到文件。
重定向
stdout
-exec 1>file
将导致标准输出成为file
以当前 shell 会话结束命名的文件。输出到显示器的所有内容都将位于文件中。重定向
stdin
- 它还可用于将 重定向stdin
到文件。例如,如果您要执行脚本文件script.sh
,则可以stdin
使用 将 重定向到该文件exec 0<script.sh
。
答案3
据我所知,它还用于重定向 bash 脚本的文件描述符(例如,STDOUT、STDERR、STDIN)。
举例来说,您可以使用 STDIN 重定向从文件而不是从键盘读取,并通过 STDOUT(或者根据程序的不同可以是 STDERR)重定向将数据写入文件而不是终端。