簡體   English   中英

bash從函數內部退出腳本

[英]bash exit script from inside a function

在某些情況下,您希望從函數內部終止腳本:

function die_if_fatal(){
    ....
    [ fatal ] && <termination statement>
}

如果腳本來源, $ . script $ . script ,終止聲明是:

  • return ,一如預期,將模具返回,但不會完成了劇本
  • exit終止會話(不返回腳本)。

現在,如果腳本被執行: chmod +x script; ./script chmod +x script; ./script

  • return ,一如預期,將模具返回,但不會完成了劇本
  • exit不會返回die並終止腳本。

簡單的方法是使用返回代碼並在返回時檢查它們,但是,我需要停止父代,而不修改調用者腳本。

有一些替代方法可以解決這個問題,但是,想象一下你在復雜的腳本中是5級,你會發現腳本必須結束; 也許是一個“魔術”退出代碼? 我只想要源代碼上的執行行為。

我正在尋找一個簡單的聲明,以結束正在運行的源腳本。

在采購時,從函數內部完成腳本的正確方法是什么?

假設您的腳本不會從循環內部獲取,您可以將腳本的主體封裝到一個人工的一次性循環中,並使用break命令break腳本。

將這個想法形式化並提供一些支持實用程序,您的腳本必須具有以下結構:

#!/bin/bash

my_exit_code=''
bailout() {
    my_exit_code=${1:-0}

    # hopefully there will be less than 10000 enclosing loops
    break 10000
}

set_exit_code() {
    local s=$?
    if [[ -z $my_exit_code ]]
    then
        return $s
    fi
    return $my_exit_code
}

###### functions #######

# Define your functions here.
#
# Finish the script from inside a function by calling 'bailout [exit_code]'

#### end functions #####

for dummy in once;
do

    # main body of the script
    # 
    # finish the script by calling 'bailout [exit_code]'

done
set_exit_code

我的想法是基於PGID (進程組標識符)和SID (會話標識符)。 除非您直接從會話負責人處獲取腳本,否則以下解決方案仍然有效。 另一方面,會話領導者主​​要是守護進程和交互式shell。 您可以通過ps aux | awk '$8 ~ /s/ { print }'驗證哪些進程作為會話負責人運行 ps aux | awk '$8 ~ /s/ { print }'

資源

/tmp/my_quit.sh

get_pid()
{
    pgid=$( ps -q $$ -o pgid= )
    sid=$( ps -q $$ -o sid= )
    if [[ $pgid == $sid ]]; then
        echo 0
    else
        echo $pgid
    fi
}

fatal()
{
    echo "1"
}

die_if_fatal()
{
    if [ $(fatal) -ne 0 ]; then
        pid=$( get_pid )
        if [ $pid -ne 0 ]; then
            echo "      >> Kill $pid"
            kill $pid
        else
            return
        fi
    fi
    echo "Rest of die_if_fatal's logic"
}

die_if_fatal
echo "      >> Sourced from a session leader. Will not end the process."

/tmp/pack1.sh

echo "$0: PID: $$ PGID: $( ps -q $$ -o pgid= ) SID=$( ps -q $$ -o sid= )"
echo "  >> Sourcing my_quit..."
. /tmp/my_quit.sh
echo "  >> Executing my_quit..."
/tmp/my_quit.sh

/tmp/pack2.sh

echo "$0: PID: $$ PGID: $( ps -q $$ -o pgid= ) SID=$( ps -q $$ -o sid= )"
echo "Sourcing pack1..."
. /tmp/pack1.sh
echo "Executing pack1"
/tmp/pack1.sh

用例

直接從shell執行die_if_fatal(my_quit.sh) - 上面沒有腳本

執行腳本:

[kan@pckan ~]$ /tmp/my_quit.sh 
      >> Kill 11360
Finished
[kan@pckan ~]$

源腳本:

[kan@pckan ~]$ . /tmp/my_quit.sh 
      >> Sourced from a session leader. Will not end the process.
[kan@pckan ~]$ 

pack1.sh執行 - 1級嵌套

從shell執行pack1.sh

[kan@pckan ~]$ /tmp/pack1.sh 
/tmp/pack1.sh: PID: 11260 PGID: 11260 SID= 1630
  >> Sourcing my_quit...
      >> Kill 11260
Finished
[kan@pckan ~]$

從shell采購pack1.sh

[kan@pckan ~]$ . /tmp/pack1.sh 
/bin/bash: PID: 1630 PGID:  1630 SID= 1630
  >> Sourcing my_quit...
      >> Sourced from a session leader. Will not end the process.
  >> Executing my_quit...
      >> Kill 11316
Finished
[kan@pckan ~]$

pack2.sh執行 - 2個(可能更多)嵌套級別

從shell執行pack2.sh:

[kan@pckan ~]$ /tmp/pack2.sh
/tmp/pack2.sh: PID: 11535 PGID: 11535 SID= 1630
Sourcing pack1...
/tmp/pack2.sh: PID: 11535 PGID: 11535 SID= 1630
  >> Sourcing my_quit...
      >> Kill 11535
Finished
[kan@pckan ~]$ 

從shell采購pack2.sh:

[kan@pckan ~]$ . /tmp/pack2.sh
/bin/bash: PID: 1630 PGID:  1630 SID= 1630
Sourcing pack1...
/bin/bash: PID: 1630 PGID:  1630 SID= 1630
  >> Sourcing my_quit...
      >> Sourced from a session leader. Will not end the process.
  >> Executing my_quit...
      >> Kill 11618
Finished
Executing pack1
/tmp/pack1.sh: PID: 11627 PGID: 11627 SID= 1630
  >> Sourcing my_quit...
      >> Kill 11627
Finished
[kan@pckan ~]$ 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM