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 / 问题 / 458760
Accepted
Harry
Harry
Asked: 2018-07-27 22:57:12 +0800 CST2018-07-27 22:57:12 +0800 CST 2018-07-27 22:57:12 +0800 CST

后台函数 F 的 PID,在 F 内的子 shell 中调用的命令中

  • 772

在foo后台运行时,BASHPIDof foo( ) 在 vi​​a 的主体内bashpid_of_foo不可用,因为它们是通过以下的命令替换功能调用的:bar_1bar_n$BASHPIDbash

function foo() {
    local bashpid_of_foo=$BASHPID
    local output

    # desired to be shared by all Command Substitutions
    # in the body of this function.
    local log=/path/to/log.$BASHPID

    ... >> $log

    output=$(bar_1 ...)
      ...
    output=$(bar_n ...)
}

function bar_1() {
   # log only specific (and NOT all) messages
   # to the shared log file of the invoking thread.
    ... >> /path/to/log.$BASHPID
}

foo &
foo &

问题:是否有绕过上述限制的优雅方法,而无需bashpid_of_foo通过临时环境变量或外部磁盘文件?

我所说的优雅,是指bar_*仅依靠 bash 提供的特性来保持接口和函数体的清洁。(例如BASHPID是一个bash特征。)

如果我尝试BASHPID像这样覆盖 的值,

out_1=$(BASHPID=$BASHPID bar_1 ...)

...它(正确地)抱怨BASHPID是一个只读变量。

编辑:(1)添加了bar_1上面的定义。(2) 在后台添加了第二次调用foo。每次foo调用都需要维护自己的日志文件,因为写入公共文件可能会导致内容乱码。

注意:无论在. foo_ _ 可以在后台运行多个实例。foo/path/to/log.$BASHPID foofoo

bash process
  • 2 2 个回答
  • 64 Views

2 个回答

  • Voted
  1. slm
    2018-07-27T23:31:03+08:002018-07-27T23:31:03+08:00

    注意: 关于您的一般问题$BASHPID,这是只读的,您不能对其进行操作。这是设计使然。

    通常我的一般建议是,当您使用这样的 Bash 脚本达到复杂程度时,是时候将其转移到 Python、Ruby 等等。


    你的例子

    我想我不明白你的问题是什么,这对我有用:

    $ cat subby.bash
    #!/bin/bash
    
    function foo() {
        local bashpid_of_foo=$BASHPID
        local output=blipblop
    
        echo "foo: $bashpid_of_foo"
        echo "foo: $output"
        out_1=$(echo $bashpid_of_foo)
        out_n=$(echo $output)
        echo "out_1: $out_1"
        echo "out_n: $out_n"
    }
    
    foo &
    
    
    $ ./subby.bash
    foo: 4900
    foo: blipblop
    out_1: 4900
    out_n: blipblop
    

    增加出口

    如果我们通过制作bar_1一个 shell 脚本来改变它:

    $ cat bar_1
    #!/bin/bash
    
    echo "from bar_1: $bashpid_of_foo"
    

    并像这样更改您的原始脚本:

    #!/bin/bash
    
    function foo() {
        export bashpid_of_foo=$BASHPID
        local output=blipblop
    
        echo "foo: $bashpid_of_foo"
        echo "foo: $output"
        out_1=$(echo $bashpid_of_foo)
        out_2=$(./bar_1)
        out_n=$(echo $output)
        echo "out_1: $out_1"
        echo "out_2: $out_2"
        echo "out_n: $out_n"
    }
    
    foo &
    

    我们可以看到$bashpid_of_foo正在正确导出到子shell:

    $ ./subby.bash
    foo: 5014
    foo: blipblop
    out_1: 5014
    out_2: from bar_1: 5014
    out_n: blipblop
    

    我们需要在export这里使用 a 而不仅仅是 alocal因为否则环境变量将不会被导出到任何孩子。子壳在这里是子壳。

    $ help export
    ...
       Marks each NAME for automatic export to the environment of subsequently
        executed commands.  If VALUE is supplied, assign VALUE before exporting.
    
    • 1
  2. Best Answer
    Kusalananda
    2018-07-28T01:28:57+08:002018-07-28T01:28:57+08:00
    #!/bin/bash
    
    bar () {
        # bashpid is set in our environment from the calling function
        printf 'bar BASHPID = %d, bar bashpid = %d\n' "$BASHPID" "$bashpid"
    
        # in your case, you would have...
    
        local logfile="/some/path/to/log.$bashpid"
    
        # etc.
    }
    
    foo () {
        local bashpid="$BASHPID"
        local message
    
        local logfile="/some/path/to/log.$BASHPID"
    
        message=$( bashpid="$bashpid" bar ); printf 'Message from bar: %s\n' "$message"
        message=$( bashpid="$bashpid" bar ); printf 'Message from bar: %s\n' "$message"
        message=$( bashpid="$bashpid" bar ); printf 'Message from bar: %s\n' "$message"
        message=$( bashpid="$bashpid" bar ); printf 'Message from bar: %s\n' "$message"
    }
    
    foo &
    foo &
    foo &
    
    wait
    

    示例运行:

    $ bash script.sh
    Message from bar: bar BASHPID = 71979, bar bashpid = 18461
    Message from bar: bar BASHPID = 7420, bar bashpid = 71036
    Message from bar: bar BASHPID = 6109, bar bashpid = 18461
    Message from bar: bar BASHPID = 27868, bar bashpid = 71036
    Message from bar: bar BASHPID = 44547, bar bashpid = 60086
    Message from bar: bar BASHPID = 69310, bar bashpid = 71036
    Message from bar: bar BASHPID = 37649, bar bashpid = 60086
    Message from bar: bar BASHPID = 15999, bar bashpid = 71036
    Message from bar: bar BASHPID = 81520, bar bashpid = 18461
    Message from bar: bar BASHPID = 92568, bar bashpid = 60086
    Message from bar: bar BASHPID = 72438, bar bashpid = 18461
    Message from bar: bar BASHPID = 15094, bar bashpid = 60086
    

    foo对于脚本主要部分中的每次调用,bar将进行四次调用并产生四行输出。如您所见,只有三个唯一bashpid编号,每个编号都来自一次foo调用。

    $bashpid从footo传递的另一种方法bar显然是将它作为命令行参数传递并使用local bashpid="$1"inbar或类似的东西接收它,但你说你不想这样做。

    • 1

相关问题

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

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

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

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

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

Sidebar

Stats

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

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

    • 4 个回答
  • Marko Smith

    ssh 无法协商:“找不到匹配的密码”,正在拒绝 cbc

    • 4 个回答
  • Marko Smith

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

    • 5 个回答
  • Marko Smith

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

    • 3 个回答
  • Marko Smith

    如何卸载内核模块“nvidia-drm”?

    • 13 个回答
  • 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
    rocky 如何将 GPG 私钥和公钥导出到文件 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Wong Jia Hau ssh-add 返回:“连接代理时出错:没有这样的文件或目录” 2018-08-24 23:28:13 +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
  • Martin Hope
    Bagas Sanjaya 为什么 Linux 使用 LF 作为换行符? 2017-12-20 05:48:21 +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