Bash betiği kaynak - Exit yerine Error on Return?


17

Ben değilim terminalde bir bash betiği kaynak böylece ile hata çıkarken,

set -o errexit

Son derece sinir bozucu olan terminalimi öldürüyor, çünkü terminali kapatmam, başka bir tane açmam ve bazı değişkenleri sıfırlamam gerekiyor.

Şimdiye kadar

command || return

kodda satırlar tam olarak istediğimi yapıyor

set -o errexit

yapmak ... Ama tüm senaryo için yapılmasını istiyorum; sadece bir satır / komut değil

Site kurmak için komutlarla dolu bir dosyam var ve ben komut yapmamayı tercih ediyorum || dönüş

dosyadaki her satır için

Başka bir ayar seçeneği var mı, yoksa terminalden çıkmak yerine "geri dönecek" başka bir şey var mı?

- Sadece netlik için , senaryoyu öldürmek ve terminali terminalde çalışan bir hizmeti öldürmek için ctrl + C tuşlarına basmakla aynı durumda bırakmak istiyorum. command || returnbunu yapar. Ama || returndosyadaki her satıra yapışmak istemiyorum . Bu yüzden benzer bir şey arıyorum set -o errexit, bu terminalin kapanmasına neden olmaz

--- Not: İçinde iki satır bulunan aptal bir senaryo oluşturma (super.sh):

create_path=~/Desktop/site_builder/create.sh
source $create_path blah

Ve set -o errexitcreate.sh dosyasının üstüne yerleştirerek ,

beklediğim gibi çalışıyor. Ancak, sadece iki satırlı bir dosya oluşturmak zorundasınız, sadece terminalden çağırmak yerine başka bir bash betiği çağırmak için. Ugghhh

İşte bazı örnekler:

super.sh içinde

#!/bin/bash

create_path=~/Desktop/site_builder/create.sh
source $create_path blah

create.sh dosyasında

#!/bin/bash
set -o errexit
#line below this is a line that fails and will cause the script to stop and return to the terminal as expected 
sed "s/@@SITE_NAME@@/$dirname" 
~/Desktop/site_builder/template_files/base.html > ~/Desktop/$dirname/templates/base.html # a line with a stupid error

terminalde:

 $ bash super.sh

beklendiği gibi çıktı:

my-mac$

Bu çalışıyor. Ne sinir bozucu bir çözüm.

Ben istiyorum üzerime terminali kapalı kalmadan D: ideal olarak, terminal değil super.sh dosyasından aptal super.sh dosyasında ne yürütmek. Yapmaya çalıştığım şey bu:

terminal komutu:

my-mac$ source $create_path blah

create.sh içinde hala var set -o errexit

İşte terminaldeki çıkış

    sed: 1: "s/@@SITE_NAME@@/blah": unterminated substitute in regular expression
Saving session...
...copying shared history...
...saving history...truncating history files...
...completed.

[Process completed]

Ve sonra terminal donmuş. Ctrl + C çalışmıyor, Ctrl + D de çalışmıyor

Bunun yerine, set -o errexitsadece command || returncreate.sh dosyasında her yerde ifadeleri kullanırsanız , o zaman tam olarak ne istediğimi alıyorum, supser.sh satırlarını doğrudan terminalde yürütürken (terminalden super.sh çağırmak yerine). Ama bu da pratik bir çözüm değil.

Not: @terdon'un sadece bir çocuk kabuğunu yumurtlama hakkındaki cevabını beğendim, bu yüzden terminalin yerine komut dosyası aracılığıyla bir alt kabuk yumurtlama bitirdim, o ( )da tüm komut dosyası etrafında parantez kullanarak cevabını gösterdi. çalışır.


Bunu bir senaryoda mı yoksa elle mi yapıyorsunuz?
terdon

Terminalde kaynak olan dosyayı arıyorum. Gibi: source $file_path argumentKomut dosyası ben denilen aynı kabuk yürütülmektedir (ne source, bana söylendi ... ve durum böyle davranır) command || returnifadeler terminalde yürütüyorum dosya

Tamam, set nerede çalışıyor? Kaynak kodda mı yoksa manuel olarak mı çalıştırıyorsunuz? Kopyalayabileceğimiz ve deneyebileceğimiz basit bir örnek ekleyebiliyorsanız bu cevaplamak çok daha kolay olacaktır. Bir fikrim var, ancak çalıştığından emin olmak için bir test yöntemine ihtiyacım var.
terdon

Orijinal yayına bu konuda yardımcı olabilecek bir Not ekledim. Ama senin de önerdiğin gibi yapacağım.

Yanıtlar:


5

Sadece dosyayı güvenli bir şekilde kaynaklayın:

source the-source-file || true

... bu durumda bile, genel komut başarısız sourceolmaz.


Aslında, istediğim gibi olduğunu düşündüm, ama terminalimin yavaş olduğu ortaya çıktı ... Aslında hatayla terminale dönmek istiyorum, (yani parçadaki tüm betiği durdur). source file || true Bunu yapmaz source file || return , bunu terminale

Dosya kaynak size bir kabuk istemine dönmüyor ??
Jeff Schaller

benim terminalde olan budur: Jills-MBP:~ jillr$ source ~/Desktop/site_builder/create.sh blah || trueSadece betiğin bir sonraki bölümünü başarısız olarak yürütür, bu yüzden true yerine döner. Çalışmış olan tek şey command || return, aptal olan tüm komutlar için gerçek dosyadaki ifadelerdir. Hepsini bir fonksiyona atma function || return, sonra dosya sonunda çağırmak ya da herhangi bir iyi olur bilmiyorum.

Açıkça || returnbaşarısız olan bir komutu koyarsanız , evet, geri döner. Ana / ebeveyn kabuğunun çıkmasını engellemeye çalıştığımızı sanıyordum?
Jeff Schaller

Evet, terminalin gerçekten çıkmasını önlemek istiyorum. Çünkü terminalden çıkmak istemiyorum. Senaryodan çıkmak istiyorum. Koddaki tek tek komutların dönüşü komut dosyasından çıkar ve terminalimi, sunucuyu terminalden çalıştırmak gibi bir işlemi öldürmek için Ctrl + C tuşlarına basmakla aynı durumda bırakır. Komut yazmaktan kaçınmak istiyorum || dosyadaki her satır için geri dönüş: D

3

Bu başarmak için gereken tek şey (bir sanal ortam oluşturmak sonra etkinleştirmek, daha sonra bir bash komut dosyasından gereksinimleri yüklemek) için çalışır:

komut dosyasından bir alt kabuk / alt kabuk oluşturun:

stupid_file.sh

(
set -o errexit
#bunch of commands
#one line fails
)

stupid_file dosyasını kullanarak şunları çalıştırın:

source stupid_file.sh <file arguments here> || true

SON.

** bir yay alır **

(kredi Jeff ve Terdon'a gider)


1
Bu, komut dosyasını kaynaklanmak yerine yürütmekten farklı değildir.
chepner

@chepner hmmm. Güzel. Sadece aramayı denemeliyim bash $create_path blahve hala çıkıp aynı şekilde yürütülüp yürütülmediğini ve hala sanal ortamıma doğru bir şekilde yükleyip yüklemediğini görmem gerekecek . Şimdi zaman doldu.

Size zaman kazandıracağım: ("şeyler yüklerse" geçerli kabuğunuzda ortam değişkenleri ayarlamak anlamına gelirse (...)) ve parantez içindeki tüm atamalar yalnızca bu alt kabuğu etkiler. foo=3; (foo=5); echo "$foo"5 değil, 3 çıktı.
chepner

@ chepner tam olarak değil. source fileTerminalden arama yapamıyorum ve aynı sonuçları beklemiyorum. Çünkü bu hiç işe yaramadı. Aynı sonuçları elde etmenin tek zamanı, ister terminal aracılığıyla ister komut dosyasından olsun açık bir şekilde alt kabuk oluşturduğum zamandır. Ancak betiği çalıştırmak ve aynı sonuçları elde etmek bashyerine kullanabilirim source, ancak

@chepner tarafından yükleme şeyler, aslında sanal bir ortam oluşturmak, o sanal ortamı etkinleştirmek ve daha sonra pip install -r $apath/requirements.txtbu etkin ortamda yürütmek demek . Bu yüzden senaryoyu aramak için ilk etapta kaynak kullandım

1

Basit bir çözüm olarak, geçerli kabuğunuzda bir kabuk çalıştırabilir ve oradan kaynak yapabilirsiniz. Gibi bir şey:

  1. Yeni bir terminal açın ve her şeyi istediğiniz gibi ayarlayın. Bazı ortam değişkenlerinden ve benzerlerinden bahsettiniz. Onları buraya kurun.

  2. Bu terminalde yeni bir kabuk başlatın. Örneğin bash,.

  3. İşini yap. Komut dosyanızı kaynaklayın. Eğer çıkarsa, sadece ilk mermiye atılırsınız ve her şey hala kurulur. Sadece bashtekrar koş ve işine geri döndün.

Göstermek için, kaynak çalıştırmaya çalışırsanız başarısız olacak bu komut dosyasını oluşturdum:

$ cat /home/terdon/scripts/bar.sh
set -o errexit
var='bar

Bir iç içe kabuk oturumu başlatmak ve sonra kaynak (bir sourcekomut için taşınabilir adı kullanıyorum .;; sourcebir bashizm olduğunu unutmayın) ne olacağını görelim:

parent-shell $ bash      ## start a new shell
child-shell $ . ~/scripts/bar.sh
bash: /home/terdon/scripts/bar.sh: line 2: unexpected EOF while looking for matching `''
parent-shell $ 

Gördüğünüz gibi, sözdizimi hatası, kaynak kodun çıkmasına neden oldu, bu da kabuk oturumumun çıkmasına neden oldu, ancak iç içe bir oturum olduğu için, beni hala orijinal, ana kabuğa geri getirdi ve tüm değişkenler hala ayarlandı . Şimdi, tekrar yeni bir kabuk çalıştırın ve betiğinizin kaynağına geri dönebilirsiniz.


Bunu gerçekten çabuk deneyeceğim

Bunun amaçlanan etkisi vardır ... dezavantajı, üst kabuk için oluşturduğum değişkenlere, alt kabukta yürütmek için ihtiyacım olan değişkenlerden birini içeren alt kabukta erişilemez olmasıdır. Yürüttüğüm dosyadan bir alt kabuk oluşturmanın bir yolu var mı? Bu şekilde, hala üst kabuktaki komut dosyasını çağırabilirim ve yine de ihtiyacım olan değişkenlere erişebilir miyim? Kelimenin tam anlamıyla create_path=~/Desktop/site_builder/create.sh ebeveyn kabuğunda ayarlıyorum çünkü sık sık yapıyorum. Ve ben komut dosyası yürütmek için kaynak $ create_path [argument] çağırmak gerekir.

1
@JillRussek değişkenler alt kabuğa geçirilmiyorsa export, onları kullanmıyorsunuz demektir . Ancak tarif ettiğiniz şey gerçekten çok az mantıklı. Kulağa bir XY sorunu gibi geliyor . Nihai hedefinizin ne olduğunu açıklayan yeni bir soru göndermek isteyebilirsiniz. Eminim size tüm bu garip kaynaklardan daha iyi bir çözüm verebiliriz.
terdon

Hmm. Bunu da denebilirim. Şu anda, sadece çocuk kabuğunu terminal yerine senaryodan çıkarmak tam olarak istediğim şeyi yapıyor. Komut dosyasında sanal bir ortam oluşturmak için terminalden komut dosyasını kaynak göstermeliyim ve pip şeyler yükleyeceğim. Şimdi amaçlandığı gibi çalışıyor.

Ama haklısın, değişkenleri dışa aktarmadım, çünkü ihtiyacım olduğunu bilmiyordum: D. (Daha önce hiç çocuk kabuğu
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.