Bagaimana cara mengembalikan pengaturan dengan benar saat menjalankan skrip menggunakan "sumber"?

9

Saya sedang menulis skrip yang perlu dieksekusi menggunakan source, karena tugasnya adalah memodifikasi lingkungan. Selama skrip, saya ingin menggunakan set -esehingga kesalahan apa pun menghentikan skrip. Scriptnya terlihat seperti ini:

#!/bin/bash
set -e
# do something
cd somewhere
source anotherScript

Masalahnya adalah bahwa set -esecara alami tetap berlaku setelah skrip selesai. Bagaimana saya bisa memastikan bahwa setopsi yang diubah dikembalikan dengan benar ke nilainya ketika skrip berhenti (dengan cara apa pun - baik dengan menyelesaikan dengan sukses atau pada kesalahan)?

Petr Pudlák
sumber
stackoverflow.com/questions/29528624/…
Ciro Santilli 冠状 病毒 审查 六四 事件 事件 法轮功
Masalah yang sama (untuk opsi -x/ xtrace) dialamatkan pada jejak eksekusi Suppress untuk perintah gema?
Scott

Jawaban:

3

Persis seperti cara Anda mengaktifkannya: memanggil buitin set:

$ set -o errexit
$ set -o | grep errexit
errexit         on
$ set +o errexit
$ set -o | grep errexit
errexit         off

Dari bash(1)manual, di bawah SHELL BUILTIN COMMANDSbagian, perintah `set ':

-o option-name
The option-name can be one of the following:
    errexit Same as -e.
dawud
sumber
3
Apakah ada cara bagaimana menyimpan (semua) pengaturan ini dan mengembalikannya nanti?
Petr Pudlák
Jalankan set -ountuk mengetahui pengaturan Anda saat ini. Jadilah eksplisit saat mengatur / membatalkan pengaturan pada skrip Anda.
dawud
12

Perintah ini set +omencantumkan pengaturan saat ini sebagai perintah yang mengembalikan keadaan yang sama, misalnya

$ set +o
set +o allexport
set -o braceexpand
set -o emacs
set +o errexit
set +o errtrace
...

Anda dapat dengan mudah mengembalikan semua opsi nanti, jika Anda menyimpan output ini ke variabel shell:

SAVED_OPTIONS=$(set +o)
set -e
# do something
eval "$SAVED_OPTIONS"

Bash juga menyertakan sejumlah opsi non-standar (bukan POSIX) yang disesuaikan menggunakan shoptperintah. Perintah shopt -pini dapat digunakan untuk menyimpan opsi-opsi ini dengan cara yang sama.

Jika Anda hanya ingin menyimpan dan mengembalikan satu opsi, Anda dapat menggunakan variabel $ - environment, yang mencantumkan set opsi saat ini sebagai huruf, misalnya

$ echo $-
himBH

Anda dapat menggunakan sesuatu seperti ini untuk menyimpan dan mengembalikan opsi tertentu:

[[ $- = *e* ]]
SAVED_ERREXIT=$?
set -e
# do something
(( $SAVED_ERREXIT )) && set +e
Seppo Enarvi
sumber
Perhatikan bahwa sangat penting untuk tidak melewatkan tanda kutip di sekitar "$ SAVED_OPTIONS" di panggilan eval.
Matt
3

Gunakan perangkap RETURN

RETURN jebakan juga berfungsi untuk skrip bersumber.

Perintah yang ditentukan dengan RETURNperangkap dieksekusi sebelum eksekusi dilanjutkan setelah fungsi shell atau skrip shell dieksekusi dengan .atau sourcekembali.

- https://www.gnu.org/software/bash/manual/bash.html

main_script.sh

#!/usr/bin/env bash
echo "inside main script"
shopt -o errexit
source a_script_to_be_sourced.sh
echo "back inside main script"
shopt -o errexit

a_script_to_be_sourced.sh

trap "$(shopt -p -o errexit)" RETURN
set -e # Equivalents: set -o errexit; shopt -s -o errexit
echo "inside sourced script"
shopt -o errexit

Uji

$ ./main_script.sh 
inside main script
errexit         off
inside sourced script
errexit         on
back inside main script
errexit         off
Robin A. Meade
sumber
2

Mengembalikan pengaturan yang diaktifkan sebelumnya dapat dengan cepat dilakukan sebagai:

PREV_SETTING=$-  # e.g. himxBH  (there was xtrace)

set +x
# do your script without xtrace, ...

set -$PREV_SETTING

Sebaliknya (mengembalikan ke keadaan tidak aktif) AFAIK tidak ada jalan pintas dan jawaban Seppo mencakup semua kasus.

F Pereira
sumber
Kode Anda sebagai hasil tertulis -bash: set: -i: invalid optionkarena -ibendera mencatat shell interaktif.
dpw