我进行了一个实验,以查看在进程链中是否仍然可以看到Bash的导出函数,即使在不同的shell之间。
令我惊讶的是,有时候导出的函数仍然可见。
我正在寻找一个解释,即为什么Bash的特定导出函数可以在不同的shell中保持在环境中,而它并不是一个POSIX标准的环境变量。
不知何故,我有一个线索,即导出函数声明被存储为一个(标准的?)环境变量中的字符串。但是它如何在不兼容的shell中作为环境变量不可见,并且如何在环境中保持?
以下是我的实验代码:
我的系统结果显示,除了
令我惊讶的是,有时候导出的函数仍然可见。
我正在寻找一个解释,即为什么Bash的特定导出函数可以在不同的shell中保持在环境中,而它并不是一个POSIX标准的环境变量。
不知何故,我有一个线索,即导出函数声明被存储为一个(标准的?)环境变量中的字符串。但是它如何在不兼容的shell中作为环境变量不可见,并且如何在环境中保持?
以下是我的实验代码:
#!/usr/bin/env bash
LANG=C
# Declare function and export it
fn(){ printf 'Hello World\n';}
export -f fn
# Standard usage, call exported function within a child bash
bash -c fn
# Available shells for tests
available_shells=()
for sh in ash bash dash ksh tcsh zsh
do
if shell_path=$(command -v "$sh" 2> /dev/null)
then
available_shells+=("$shell_path")
real_shell_path=$(realpath "$shell_path")
shell_version=$(
read -r pkg < <(apt-file search "${real_shell_path#/usr}" | awk -F: '{print $1}')
dpkg -s "$pkg" | awk '/Version:/{print $2}'
)
printf 'Found: %s\tversion: %s\n' "$shell_path" "$shell_version"
fi
done
# Test transversal visibility of exported fn through different shells
for sh in "${available_shells[@]}"; do
printf "Testing %s -c 'bash -c fn':\\n" "$sh"
"$sh" -c 'bash -c fn'
printf \\n
done
我的系统结果显示,除了
ash
和dash
之外,所有测试的外壳都保持了导出的fn
横向可见性。Hello World
Found: /usr/bin/ash version: 0.5.12-2ubuntu1
Found: /usr/bin/bash version: 5.2.15-2ubuntu1
Found: /usr/bin/dash version: 0.5.12-2ubuntu1
Found: /usr/bin/ksh version: 1.0.4-3
Found: /usr/bin/tcsh version: 6.24.07-1
Found: /usr/bin/zsh version: 5.9-4
Testing /usr/bin/ash -c 'bash -c fn':
bash: line 1: fn: command not found
Testing /usr/bin/bash -c 'bash -c fn':
Hello World
Testing /usr/bin/dash -c 'bash -c fn':
bash: line 1: fn: command not found
Testing /usr/bin/ksh -c 'bash -c fn':
Hello World
Testing /usr/bin/tcsh -c 'bash -c fn':
Hello World
Testing /usr/bin/zsh -c 'bash -c fn':
Hello World