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 / 问题 / 792546
Accepted
Arch Stanton
Arch Stanton
Asked: 2025-03-16 18:52:43 +0800 CST2025-03-16 18:52:43 +0800 CST 2025-03-16 18:52:43 +0800 CST

程序用什么来读取它们的环境?

  • 772

我使用的是 Fedora,其中所有预装的 shell 显然都支持 bashism:bash --posix确实如此,甚至如此sh。不过,当我使用这个函数时,

pathprepend () {
    if [[ ":$PATH:" != *":$1:"* ]]; then
        PATH="$1${PATH:+":$PATH"}"
    fi
}

PATH从向添加目录~/.profile,Git 没有发现它。请注意,echo $PATH在我使用 Git 的 bash 会话中,确实列出了我的目录,我注意到,只是因为我使用了diff-highlight,所以在该目录中建立了符号链接,而在我开始使用上述pathprepend函数后,Git 抱怨diff-highlight缺少了该功能。恢复 POSIX 兼容PATH设置后,它恢复正常工作。

这让我想知道程序使用什么来读取它们的环境。它们是否都带有自己的机制来执行此操作?它们是否将工作留给某个系统 shell 或库?


编辑

@Bodo,这是我以前常做的~/.profile:

pathprepend () {
    if [[ ":$PATH:" != *":$1:"* ]]; then
        PATH="$1${PATH:+":$PATH"}"
    fi
}

pathprepend "$HOME/.local/bin"

我说的“POSIX 兼容”是指没有任何暴力倾向。这是我现在所拥有的~/.profile:

pathprepend () {
  case ":$PATH:" in
    *":$1:"*)
      :;;
    *)
      PATH="$1${PATH:+":$PATH"}";;
  esac
}

pathprepend "$HOME/.local/bin"

两种情况下均~/.profile来源于~/.bash_profile,其中包含

# Load the configuration for login sessions of any shell
if [[ -f "$HOME/.profile" ]]; then
  source "$HOME/.profile"
else
  echo >&2 "$HOME/.bash_profile: $HOME/.profile not found"
fi

# Load the configuration for interactive non-login Bash sessions
case "$-" in *i*)
  if [[ -f "$HOME/.bashrc" ]]; then
    source "$HOME/.bashrc"
  else
    echo >&2 "$HOME/.bash_profile: $HOME/.bashrc not found"
  fi;;
esac

我没有这样做export PATH,因为 Gordon Davisson 在我从中复制函数的答案中解释说“PATH应该已经标记为已导出,因此不需要重新导出。” 事实上,我仍然不知道,export但使用case的版本pathprepend一切正常。顺便问一下,Git 进程的父进程是什么,它是我使用的 Bash 进程吗git?

shell-script
  • 1 1 个回答
  • 878 Views

1 个回答

  • Voted
  1. Best Answer
    Stéphane Chazelas
    2025-03-16T23:20:14+08:002025-03-16T23:20:14+08:00

    程序execve(program_path, argv, envp)从执行它们的系统调用的第三个参数获取其环境。

    envp,就像argv是一个字符串数组,除了按照envp惯例字符串是var=value格式的。

    程序如何处理这些字符串取决于它们自己,但通常它们采用这些var=value字符串并将第一个字符串左边的内容解释=为环境变量的名称,将右边的内容解释为其值。

    它们通常将该列表存储起来,当它们在同一个进程或子进程中执行其他命令时,它们将同一个列表作为第三个参数传递给相应的execve()系统调用。

    C 库有用于此目的的帮助程序。该存储旁注列表是environ那里的变量,并且可以使用putenv()/ setenv()/函数来添加/修改/删除那里的变量,并且诸如 之类的函数是系统调用的包装器,可将其自动传递为。这个想法是,环境应该是执行过程中自动继承的东西¹。unsetenv()execlp()execve()environenvp

    大多数 shell 将环境变量映射到 shell 变量。

    在类似 POSIX 的 shell 中,envp名称与 shell 变量兼容的变量将转换为标有export属性的 shell 变量。并且export可以使用特殊的内置实用程序将 shell 变量提升为环境变量,以便将其传递给envp此后执行的每个命令。

    ~/.profile是会话初始化文件,当大多数 Bourne 类 shell 被调用为登录 shell时(通过在前面login添加 来实现),它会对其进行解释。csh 类 shell 的等效文件是,另请参阅zsh 的/ 。-argv[0]~/.login~/.zprofile~/.zlogin

    目前,这通常是在登录时读取的ssh(ssh host仅使用rlogin模式,而不是不登录的模式)或在虚拟终端或 中ssh host 'shell code',很少通过在图形登录会话中启动的终端仿真器来读取。rshsudo -i

    一些图形环境会尝试将用户的登录 shell 作为非交互式登录 shell 调用来启动,该调用会在登录时解释这些会话环境文件,以尝试在那里获取相同的环境变量,但并非全部。有时还会使用其他机制来定义环境变量。

    如果在登录时,您的登录 shell 是作为登录 shell 启动的,并且它类似于 Bourne(而不是 zsh),它将解释中的代码~/.profile。

    解释后,PATH="~/.local/bin${PATH:+":$PATH"}"它将更新$PATH shell变量。由于该变量将在传递给该 shell 的 中找到envp,因此该变量将被标记为 ,export并且带有其修改值的变量²将包含在envp传递给此后执行的每个命令(包括 )的 中git。如果git执行getenv("PATH"),它应该会获得该修改后的值。

    但要做到这一点,~/.profile必须由执行的进程祖先中的 shell 来解释git。


    ¹ 不要与父子关系混淆。子代从其父代继承了所有内容,但执行会清除整个内存,因此您需要环境之类的机制来传递信息。

    ² 除了 Bourne shell 之外,除非您调用 ,否则修改 shell 变量不会反映在环境变量中export。但是您在 Fedora 或任何现代系统中都找不到 Bourne shell。

    • 7

相关问题

  • 在awk中的两行之间减去相同的列

  • 打印文件行及其长度的脚本[关闭]

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

  • 按分隔符拆分并连接字符串问题

  • MySQL Select with function IN () with bash array

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