如何在另一个bash脚本中增加全局变量

时间:2015-06-03 17:04:08

标签: macos bash shell

问题,

我希望有一个bash脚本,它将有一个可以从其他bash脚本增加的全局变量。

实施例: 我有一个如下的脚本:

 #! /bin/bash
export Counter=0
   for SCRIPT in /Users/<user>/Desktop/*sh
    do
        $SCRIPT
    done
echo $Counter

该脚本将调用文件夹中的所有其他bash脚本,这些脚本将具有以下内容:

if [ "$Output" = "$Check" ]
    then
       echo "OK"
      ((Counter++))

我希望它然后递增$ Counter变量,如果它等于&#34; OK&#34;然后将该值传递回初始批处理脚本,以便我可以保留该计数器编号并在结束时总计。

关于如何去做的任何想法?

3 个答案:

答案 0 :(得分:6)

环境变量仅在一个方向传播 - 从父级到子级。因此,子进程无法更改其父级中设置的环境变量的值。

您可以使用文件系统:

export counter_file=$(mktemp "$HOME/.counter.XXXXXX")
for script in ~user/Desktop/*sh; do "$script"; done

......并且,在单个脚本中:

counter_curr=$(< "$counter_file" )
(( ++counter_curr ))
printf '%s\n' "$counter_curr" >"$counter_file"

这当前不是并发安全的,但是您当前编写的父脚本一次不会调用多个子项。

更简单的方法,假设您跟踪的值仍然相对较小,就是使用文件的大小作为计数器值的代理。为此,递增计数器就像这样简单:

printf '\n' >>"$counter_file"

...并在O(1)时间内检查其值 - 无需打开文件并读取其内容 - 就像检查文件的大小一样简单;使用GNU stat

counter=$(stat -f %z "$counter_file")

请注意,如果使用NFS等未正确实现O_APPEND的文件系统,则可能需要进行锁定才能实现并发安全。请参阅Norman Gray's answer(这是灵感来源)的工作实施。

答案 1 :(得分:2)

你可以source其他脚本,这意味着他们没有在子流程中运行,但是&#34;内联&#34;在这样的调用脚本中:

#! /bin/bash
export counter=0
   for script in /Users/<user>/Desktop/*sh
   do
       source "$script"
   done
echo $counter

但正如评论中指出的那样,如果您自己控制被调用脚本,我建议您使用此方法。如果它们例如exit或者变量相互冲突,可能会发生不好的事情。

答案 2 :(得分:1)

如上所述,你不能这样做,因为没有任何东西对应于shell脚本的'全局变量'。

如评论所示,您必须使用文件系统在脚本之间进行通信。

执行您所描述的操作的一种简单/粗略方式是简单地让每个协作脚本在文件中附加一行,并且'global count'是此文件的大小:

#! /bin/sh -
echo ping >>/tmp/scriptcountfile

然后wc -l /tmp/scriptcountfile是发生的次数。当然,那里存在潜在的竞争条件,所以类似下面的内容会对这些访问进行排序:

#! /bin/sh -
(
flock -n 9 
echo 'do stuff...'
echo ping >>/tmp/stampfile
) 9>/tmp/lockfile

flock命令在Linux上可用,但不可移植。)

当然,那么你可以通过让脚本通过管道和套接字发送东西来开始做更好的事情,但这有点过头了。