在当前bash(sh)中执行脚本和注册函数

在研究《管理Python虚拟环境的脚本》时,我们使用了source指令而没有使用sh或者bash来执行脚本,就是因为source指令可以让脚本在当前bash(sh)中执行;而sh或者bash则会新启动一个bash来执行。

我们可以通过下面这个脚本做测试

bash 复制代码
# test.sh
# 用一个数组保存进程ID和进程名
processInfo=()

# 查找父进程的进程号
findParentID() {
    if [ $1 = $2 ]; then
        # 如果父进程号等于目标进程号,说明已经找到了父进程
        # 打印所有进程信息
        echo "processInfo: ${processInfo[@]}"
        return
    else
        # 获取当前进程的父进程号
        parentID=$(ps -o ppid= $1)
        # 获取父进程的名字
        parentName=$(ps -o comm= $parentID)

        # 将父进程号和父进程名保存到数组中
        processInfo+=($parentID $parentName)

        findParentID $parentID $2
    fi
}

currentName=$(ps -o comm= $$)
processInfo+=($$ $currentName)
findParentID $$ $1

bash

bash 复制代码
bash test.sh $$

processInfo: 45322 bash 40883 bash

当前bash的进程ID是40883,新启动的bash的进程ID是45322。

source

bash 复制代码
source test.sh $$

processInfo: 40883 bash

可以见得没有启动新的bash程序。

source还可以让自动注册脚本中的函数。

比如上面指令让脚本中的findParentID方法可以直接被使用。

bash 复制代码
findParentID $$ $$

processInfo: 40883 bash

相似的应用在Python虚拟环境中也有体现。

比如我们启动一个虚拟环境,使用下面的命令

bash 复制代码
source .env/bin/activate

而退出虚拟环境的方法deactivate则注册在.env/bin/activate文件中

bash 复制代码
# This file must be used with "source bin/activate" *from bash*
# you cannot run it directly

deactivate () {
    # reset old environment variables
    if [ -n "${_OLD_VIRTUAL_PATH:-}" ] ; then
        PATH="${_OLD_VIRTUAL_PATH:-}"
        export PATH
        unset _OLD_VIRTUAL_PATH
    fi
    if [ -n "${_OLD_VIRTUAL_PYTHONHOME:-}" ] ; then
        PYTHONHOME="${_OLD_VIRTUAL_PYTHONHOME:-}"
        export PYTHONHOME
        unset _OLD_VIRTUAL_PYTHONHOME
    fi

    # This should detect bash and zsh, which have a hash command that must
    # be called to get it to forget past commands.  Without forgetting
    # past commands the $PATH changes we made may not be respected
    if [ -n "${BASH:-}" -o -n "${ZSH_VERSION:-}" ] ; then
        hash -r 2> /dev/null
    fi

    if [ -n "${_OLD_VIRTUAL_PS1:-}" ] ; then
        PS1="${_OLD_VIRTUAL_PS1:-}"
        export PS1
        unset _OLD_VIRTUAL_PS1
    fi

    unset VIRTUAL_ENV
    unset VIRTUAL_ENV_PROMPT
    if [ ! "${1:-}" = "nondestructive" ] ; then
    # Self destruct!
        unset -f deactivate
    fi
}

# unset irrelevant variables
deactivate nondestructive

VIRTUAL_ENV="/home/fangliang/numpy-example/.env"
export VIRTUAL_ENV

_OLD_VIRTUAL_PATH="$PATH"
PATH="$VIRTUAL_ENV/bin:$PATH"
export PATH

# unset PYTHONHOME if set
# this will fail if PYTHONHOME is set to the empty string (which is bad anyway)
# could use `if (set -u; : $PYTHONHOME) ;` in bash
if [ -n "${PYTHONHOME:-}" ] ; then
    _OLD_VIRTUAL_PYTHONHOME="${PYTHONHOME:-}"
    unset PYTHONHOME
fi

if [ -z "${VIRTUAL_ENV_DISABLE_PROMPT:-}" ] ; then
    _OLD_VIRTUAL_PS1="${PS1:-}"
    PS1="(.env) ${PS1:-}"
    export PS1
    VIRTUAL_ENV_PROMPT="(.env) "
    export VIRTUAL_ENV_PROMPT
fi

# This should detect bash and zsh, which have a hash command that must
# be called to get it to forget past commands.  Without forgetting
# past commands the $PATH changes we made may not be respected
if [ -n "${BASH:-}" -o -n "${ZSH_VERSION:-}" ] ; then
    hash -r 2> /dev/null
fi

如果我们使用bash来执行,则因为虚拟环境会在新启动的bash中存在,并会快速退出。回到我们原来的bash中时,已经不是虚拟环境了。相应的deactivate方法也没注册到环境中。

所以如果我们希望脚本对当前bash有所影响,就要使用source去执行脚本;如果不希望影响当前bash,则可以使用bash或者sh去执行。

需要注意的是,bash并不等价于sh。sh(Bourne Shell)是1978年由史蒂夫·伯恩编写的shell;bash(Bourne-Again Shell)是1987年由布莱恩·福克斯为GNU计划编写的Unix shell。主要目标是与POSIX标准保持一致,同时兼顾对sh的兼容,是各种Linux发行版标准配置的Shell。比如上面test.sh使用bash可以正确执行,而sh执行就会报错。

相关推荐
韩楚风1 小时前
【linux 多进程并发】linux进程状态与生命周期各阶段转换,进程状态查看分析,助力高性能优化
linux·服务器·性能优化·架构·gnu
陈苏同学1 小时前
4. 将pycharm本地项目同步到(Linux)服务器上——深度学习·科研实践·从0到1
linux·服务器·ide·人工智能·python·深度学习·pycharm
Ambition_LAO1 小时前
解决:进入 WSL(Windows Subsystem for Linux)以及将 PyCharm 2024 连接到 WSL
linux·pycharm
Pythonliu71 小时前
茴香豆 + Qwen-7B-Chat-Int8
linux·运维·服务器
你疯了抱抱我1 小时前
【RockyLinux 9.4】安装 NVIDIA 驱动,改变分辨率,避坑版本。(CentOS 系列也能用)
linux·运维·centos
追风赶月、1 小时前
【Linux】进程地址空间(初步了解)
linux
栎栎学编程1 小时前
Linux中环境变量
linux
挥剑决浮云 -2 小时前
Linux 之 安装软件、GCC编译器、Linux 操作系统基础
linux·服务器·c语言·c++·经验分享·笔记
小O_好好学3 小时前
CentOS 7文件系统
linux·运维·centos
x晕x4 小时前
Linux dlsym符号查找疑惑分析
linux·运维·服务器