AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / unix / 问题 / 717671
Accepted
Richie Thomas
Richie Thomas
Asked: 2022-09-18 16:02:48 +0800 CST2022-09-18 16:02:48 +0800 CST 2022-09-18 16:02:48 +0800 CST

为什么 `exec -a` 不能按我预期的方式工作?

  • 772

我正在阅读exec以及如何使用该-a标志。SS64文档似乎准确;他们说:

执行:

执行命令

句法:

exec [-cl] [-a name] [command [arguments]]

选项:

-c   Causes command to be executed with an empty environment.

-l   Place a dash at the beginning of the zeroth arg passed to command.
     (This is what the login program does.)

-a   The shell passes name as the zeroth argument to command.

为了测试这一点,我编写了两个脚本,一个名为foo/baz,一个名为foo/buzz:

#!/usr/bin/env bash
# foo/baz

exec -a blah ./foo/bar 1 2
#!/usr/bin/env bash
# foo/buzz

exec ./foo/bar 1 2

这些脚本中的每一个都运行相同的子脚本 ,foo/bar它执行以下操作:

#!/usr/bin/env bash

echo "Hello world"
echo "0: $0"
echo "1: $1"
echo "2: $2"

我的目标是看看-a对第 0 次和随后的论点有什么影响。如果-a导致第 0 个参数更改为您传递给-a标志的参数,那么当我运行时我希望第 0 个参数foo/baz是blah,因为这就是我传递给-a. 但是,当我运行脚本时,两种情况下的输出都是相同的:

~/Workspace/OpenSource (master)  $ ./foo/baz 
Hello world
0: /Users/richiethomas/Workspace/OpenSource/foo/bar
1: 1
2: 2
~/Workspace/OpenSource (master)  $ ./foo/buzz
Hello world
0: /Users/richiethomas/Workspace/OpenSource/foo/bar
1: 1
2: 2

难道我做错了什么?还是我的期望不正确?

另外,一个相关的问题——覆盖第 0 个参数的用例是什么,而不是仅仅通过 $1、$2、$3 等访问任何传入的参数?

bash
  • 3 3 个回答
  • 618 Views

3 个回答

  • Voted
  1. Best Answer
    larsks
    2022-09-18T16:25:27+08:002022-09-18T16:25:27+08:00

    覆盖第 0 个参数的用例是什么......?

    一些程序会根据调用方式改变它们的行为。例如,busybox是一个以这种方式运行的多调用二进制文件。根据第零个参数的值,使用exec -a我们会得到不同的行为:

    $ bash -c 'exec -a date /usr/sbin/busybox'
    Sat Sep 17 20:22:14 EDT 2022
    $ bash -c 'exec -a uptime /usr/sbin/busybox'
     20:22:17 up 23:48,  load average: 0.10, 0.20, 0.15
    

    这也表明其exec -a <something>行为与记录的一样。

    难道我做错了什么?还是我的期望不正确?

    这里的问题是您正在使用 shell 脚本。当您./foo/baz在命令行上输入时,您实际上并没有运行名为 的命令./foo/baz:您正在运行类似/bin/bash /path/to/foo/baz. 虽然exec -a影响传递给外壳的第零个参数......外壳不在乎,它在设置对外壳脚本可见的变量时使用自己的逻辑,包括$0(包含脚本名称)和位置参数$1,$2...(其中包含脚本的参数)。

    (这并不特定于 shell 脚本——几乎任何解释代码都是如此。)

    • 13
  2. Joseph Sible-Reinstate Monica
    2022-09-19T07:56:31+08:002022-09-19T07:56:31+08:00

    这是因为您正在调用解释脚本而不是本机二进制文件。编译这个 C 程序,把结果放在./foo/bar你的脚本原来的位置:

    #include <stdio.h>
    
    int main(int argc, char **argv) {
        puts("Hello world");
        for(int i = 0; i < argc; ++i)
            printf("%d: %s\n", i, argv[i]);
    }
    

    一旦你这样做了,你就会看到你所期望的行为。差异的原因是在调用解释脚本时,argv[0]被劫持告诉解释器脚本的名称。通常这不会被注意到,因为在大多数情况下,无论如何都是这样。你只是注意到它,因为你不遗余力地让它与众不同。

    • 4
  3. QuartzCristal
    2022-09-18T19:01:27+08:002022-09-18T19:01:27+08:00

    关键是它将为该命令行上的命令exec设置唯一。$0

    试试,例如:

    $ bash
    
    $ exec -a SomeName sh -c 'echo "The name is: $0"'
    The name is: SomeName
    

    恰好由于 exec 替换了 shell,shell 关闭了,当它结束时,shell 进程也结束了。bash这就是为什么您需要使用该命令请求一个新的 shell 。如果没有,shell 将关闭并且也将关闭终端。

    如果您想遵循 exec 命令的功能,请尝试以下操作:

    $ strace -fe execve bash -c 'exec -a SomeName echo test' one two
    execve("/usr/bin/bash", ["bash", "-c", "exec -a SomeName echo test", "one", "two"], 0x7ffdca326e60 /* 77 vars */) = 0
    execve("/usr/bin/echo", ["SomeName", "test"], 0x55d4dcf02c50 /* 76 vars */) = 0
    test
    +++ exited with 0 +++
    

    这对于在调用名称更改时进行一些可执行更改很有用:

    $ ( exec -a date -- busybox -ud '12:34' +'%F %T %Z' )
    2022-09-18 12:34:00 UTC
    
    $ ( exec -a ls busybox )
    fileone
    filetwo
    
    • 1

相关问题

  • 通过命令的标准输出以编程方式导出环境变量[重复]

  • 从文本文件传递变量的奇怪问题

  • 虽然行读取保持转义空间?

  • `tee` 和 `bash` 进程替换顺序

  • 运行一个非常慢的脚本直到它成功

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    模块 i915 可能缺少固件 /lib/firmware/i915/*

    • 3 个回答
  • Marko Smith

    无法获取 jessie backports 存储库

    • 4 个回答
  • Marko Smith

    如何将 GPG 私钥和公钥导出到文件

    • 4 个回答
  • Marko Smith

    我们如何运行存储在变量中的命令?

    • 5 个回答
  • Marko Smith

    如何配置 systemd-resolved 和 systemd-networkd 以使用本地 DNS 服务器来解析本地域和远程 DNS 服务器来解析远程域?

    • 3 个回答
  • Marko Smith

    dist-upgrade 后 Kali Linux 中的 apt-get update 错误 [重复]

    • 2 个回答
  • Marko Smith

    如何从 systemctl 服务日志中查看最新的 x 行

    • 5 个回答
  • Marko Smith

    Nano - 跳转到文件末尾

    • 8 个回答
  • Marko Smith

    grub 错误:你需要先加载内核

    • 4 个回答
  • Marko Smith

    如何下载软件包而不是使用 apt-get 命令安装它?

    • 7 个回答
  • Martin Hope
    user12345 无法获取 jessie backports 存储库 2019-03-27 04:39:28 +0800 CST
  • Martin Hope
    Carl 为什么大多数 systemd 示例都包含 WantedBy=multi-user.target? 2019-03-15 11:49:25 +0800 CST
  • Martin Hope
    rocky 如何将 GPG 私钥和公钥导出到文件 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Evan Carroll systemctl 状态显示:“状态:降级” 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim 我们如何运行存储在变量中的命令? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S 为什么 /dev/null 是一个文件?为什么它的功能不作为一个简单的程序来实现? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 如何从 systemctl 服务日志中查看最新的 x 行 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - 跳转到文件末尾 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla 为什么真假这么大? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis 在一个巨大的(70GB)、一行、文本文件中替换字符串 2017-12-30 06:58:33 +0800 CST

热门标签

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve