Tìm nguồn của tập lệnh Bash - Trả về Lỗi, thay vì Thoát?


15

Tôi đang tìm nguồn cung cấp một tập lệnh bash trong thiết bị đầu cuối , do đó không có lỗi với

set -o errexit

Giết thiết bị đầu cuối của tôi, đó là TUYỆT VỜI, bởi vì tôi phải đóng thiết bị đầu cuối, mở một thiết bị khác và đặt lại một số biến.

Cho đến nay, sử dụng

command || return

trong các kịch bản, đang thực hiện chính xác những gì tôi muốn

set -o errexit

để làm ... Nhưng tôi muốn nó được thực hiện cho toàn bộ kịch bản; không chỉ một dòng / lệnh

Tôi có một tệp chứa đầy đủ các lệnh để thiết lập trang web và tôi không muốn thực hiện lệnh | | trở về

cho mỗi dòng trong tệp

Có một tùy chọn thiết lập khác, hoặc một cái gì đó khác sẽ chỉ "trở lại" thay vì thoát khỏi thiết bị đầu cuối?

- Để rõ ràng , tôi muốn giết tập lệnh và để thiết bị đầu cuối ở trạng thái tương tự nhấn ctrl + C để giết dịch vụ đang chạy trong thiết bị đầu cuối. command || returnlàm điều đó Nhưng tôi không muốn giải || returnquyết từng dòng trong tệp. Vì vậy, tôi đang tìm kiếm một cái gì đó tương tự set -o errexit, điều đó không làm cho thiết bị đầu cuối bị tắt

--- Lưu ý: Tạo tập lệnh câm có hai dòng trong đó (super.sh):

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

Và đặt set -o errexitở đầu của created.sh,

hoạt động chính xác như tôi mong đợi Tuy nhiên, thật ngu ngốc khi phải tạo một tệp có hai dòng trong đó, chỉ để gọi một tập lệnh bash khác, thay vì chỉ gọi nó từ thiết bị đầu cuối. Ái chà

Dưới đây là một số ví dụ:

trong super.sh

#!/bin/bash

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

trong tạo.sh

#!/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

trong thiết bị đầu cuối:

 $ bash super.sh

sản lượng như mong đợi:

my-mac$

Những công việc này. Thật là một giải pháp khó chịu.

Tôi muốn , lý tưởng nhất là thực thi những gì trong tệp super.sh ngu ngốc từ thiết bị đầu cuối, chứ không phải tệp super.sh: D, mà không cần thiết bị đầu cuối tắt với tôi. Đây là những gì xảy ra với những gì tôi đang cố gắng làm:

lệnh đầu cuối:

my-mac$ source $create_path blah

trong create.sh tôi vẫn có set -o errexit

Đây là đầu ra trên thiết bị đầu cuối

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

[Process completed]

Và sau đó thiết bị đầu cuối bị đóng băng. Ctrl + C không hoạt động, Ctrl + D cũng không

Nếu thay vì set -o errexit, nếu tôi chỉ sử dụng các command || returncâu lệnh ở mọi nơi trong tệp create.sh, thì tôi sẽ nhận được chính xác những gì tôi muốn, trong khi thực hiện các dòng trong supser.sh trực tiếp trên thiết bị đầu cuối (thay vì gọi super.sh từ thiết bị đầu cuối). Nhưng đó cũng không phải là một giải pháp thực tế.

Lưu ý: Tôi thích câu trả lời của @terdon về việc sinh ra một vỏ con nên cuối cùng tôi chỉ sinh ra một vỏ con thông qua tập lệnh thay vì thiết bị đầu cuối, như anh ấy đã thể hiện trong câu trả lời của mình bằng cách sử dụng dấu ngoặc nhọn ( ), xung quanh toàn bộ tập lệnh .. làm việc quá


Bạn đang làm điều này trong một kịch bản hoặc bằng tay?
terdon

Tôi đang gọi tập tin với nguồn trong thiết bị đầu cuối. Như trong: source $file_path argumentKịch bản đang được thực thi trong cùng một shell mà tôi đã gọi nó từ (cái gì source, tôi đã được thông báo ... và hành động như trường hợp đó) command || returnnằm trong tệp tôi đang thực thi trong thiết bị đầu cuối

OK, và tập chạy ở đâu? Đó có phải là trong tập lệnh có nguồn gốc hoặc bạn chạy nó bằng tay? Điều này sẽ dễ trả lời hơn nhiều nếu bạn có thể thêm một ví dụ đơn giản mà chúng tôi có thể sao chép và dùng thử. Tôi có một ý tưởng, nhưng tôi cần một cách thử nghiệm để chắc chắn rằng nó hoạt động.
terdon

Tôi đã thêm một ghi chú cho bài viết gốc có thể giúp với điều đó. Nhưng tôi cũng sẽ làm như bạn đề nghị.

Câu trả lời:


4

Đơn giản chỉ cần nguồn tệp với failafe:

source the-source-file || true

... Sau đó, lệnh tổng thể sẽ không thất bại, ngay cả khi sourcecó.


Trên thực tế, tôi nghĩ rằng đây là những gì tôi muốn, nhưng hóa ra thiết bị đầu cuối của tôi chỉ bị chậm ... Tôi thực sự muốn quay trở lại thiết bị đầu cuối do lỗi, (có nghĩa là dừng toàn bộ tập lệnh trong các bài hát của nó) .. vì bất kỳ lý do gì, source file || true không làm điều này, cũng không làm gì source file || return khi tôi gõ cái này vào thiết bị đầu cuối ...

Tìm nguồn tệp không đưa bạn trở lại dấu nhắc shell ??
Jeff Schaller

đây là những gì trong thiết bị đầu cuối của tôi: Jills-MBP:~ jillr$ source ~/Desktop/site_builder/create.sh blah || trueNó chỉ đơn giản thực hiện phần tiếp theo của tập lệnh khi không thành công, do đó, trả về thay vì đúng. Điều duy nhất đã làm việc là các command || returncâu lệnh trong tệp thực tế cho tất cả các lệnh, thật ngớ ngẩn. Tôi không biết nếu ném tất cả vào một chức năng thì gọi function || returnvào cuối tập tin cũng sẽ không có tác dụng gì.

Chà, nếu bạn dứt khoát đưa ra || returnmột lệnh thất bại, thì có, nó sẽ trở lại. Tôi nghĩ rằng chúng tôi đang cố gắng để giữ cho vỏ chính / phụ huynh của bạn không thoát ra?
Jeff Schaller

Có, tôi muốn giữ cho thiết bị đầu cuối thực sự thoát. Bởi vì tôi không muốn thoát khỏi thiết bị đầu cuối. Tôi muốn thoát khỏi kịch bản. Quay trở lại các lệnh riêng lẻ trong tập lệnh thoát khỏi tập lệnh và để thiết bị đầu cuối của tôi trong cùng điều kiện như nhấn Ctrl + C để giết một quá trình, chẳng hạn như chạy máy chủ tạo thành thiết bị đầu cuối, sẽ. Tôi muốn tránh viết lệnh | | trả lại cho mỗi dòng trong tệp: D

2

Đây là điều duy nhất hoạt động cho những gì tôi cần thực hiện (tạo môi trường ảo sau đó kích hoạt nó, sau đó cài đặt các yêu cầu từ tập lệnh bash):

sinh ra một vỏ con / vỏ con từ tập lệnh, như trong:

ngu_file.sh

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

chạy crazy_file bằng cách sử dụng:

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

KẾT THÚC.

** cúi chào **

(tín dụng cho Jeff và Terdon)


1
Điều này thực sự không khác gì so với việc chỉ thực hiện kịch bản thay vì tìm nguồn cung ứng.
chepner

@chepner hmmm. Mát mẻ. Tôi sẽ phải thử gọi bash $create_path blahvà xem liệu nó có thoát không, và thực hiện theo cách tương tự, và vẫn cài đặt công cụ vào môi trường ảo của tôi một cách chính xác. Hết giờ rồi.

Tôi sẽ tiết kiệm thời gian cho bạn: nó sẽ không (nếu bằng cách "cài đặt công cụ", bạn có nghĩa là đặt các biến môi trường trong trình bao hiện tại của bạn), và sẽ không (...), vì tất cả các bài tập trong ngoặc đơn chỉ có tác dụng phụ. foo=3; (foo=5); echo "$foo"sẽ xuất 3, không phải 5.
chepner

@chepner không chính xác. Tôi không thể gọi source filetừ thiết bị đầu cuối và mong đợi kết quả tương tự. Bởi vì điều đó không bao giờ làm việc. Lần duy nhất tôi nhận được kết quả tương tự là khi tôi tạo một vỏ con một cách rõ ràng, cho dù thông qua thiết bị đầu cuối, hoặc từ tập lệnh. Tuy nhiên, tôi có thể sử dụng bashthay vì sourcethực thi tập lệnh và nhận được kết quả tương tự, nhưng chỉ khi tôi thực thi tập lệnh của mình trong lớp vỏ phụ một cách rõ ràng

@chepner bằng cách cài đặt công cụ, tôi thực sự có nghĩa là tạo một môi trường ảo, kích hoạt môi trường ảo đó và sau đó thực thi pip install -r $apath/requirements.txttrong môi trường được kích hoạt đó. Đó là lý do tại sao tôi sử dụng nguồn ở nơi đầu tiên để gọi tập lệnh

0

Như một cách giải quyết đơn giản, bạn có thể chạy một trình bao trong trình bao hiện tại và nguồn ở đó. Cái gì đó như:

  1. Mở một thiết bị đầu cuối mới và thiết lập mọi thứ theo cách bạn muốn. Bạn đã đề cập đến một số biến môi trường và tương tự. Đặt chúng ở đây.

  2. Trong thiết bị đầu cuối đó, bắt đầu một vỏ mới. Ví dụ , bash.

  3. Làm việc của bạn. Nguồn kịch bản của bạn. Nếu nó thoát, bạn chỉ cần ném vào vỏ đầu tiên và mọi thứ vẫn được thiết lập. Chỉ cần chạy bashlại và bạn đã trở lại trong kinh doanh.

Để minh họa, tôi đã tạo tập lệnh này sẽ thất bại nếu bạn cố gắng tìm nguồn:

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

Chúng ta hãy xem điều gì xảy ra nếu tôi bắt đầu một phiên shell được lồng vào nhau và sau đó lấy nguồn đó (lưu ý rằng tôi đang sử dụng tên di động cho sourcelệnh , .; sourcelà một bashism):

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 $ 

Như bạn có thể thấy, lỗi cú pháp khiến tập lệnh có nguồn gốc thoát ra, do đó, khiến phiên shell của tôi thoát nhưng vì đó là phiên lồng nhau, điều đó đã đưa tôi trở lại trình bao gốc, với tất cả các biến vẫn được thiết lập . Bây giờ, chỉ cần chạy một shell mới một lần nữa và bạn có thể quay lại tìm nguồn cung cấp kịch bản của mình.


Tôi sẽ thử điều này thực sự nhanh chóng

Điều này có tác dụng dự định ... nhược điểm là các biến tôi tạo cho shell cha, không thể truy cập được trong shell con, chứa một trong các biến tôi cần để thực thi trong shell con. Có cách nào để tạo ra một subshell từ tệp tôi đang thực thi không? Bằng cách đó, tôi vẫn có thể gọi tập lệnh trong shell cha và vẫn có thể truy cập các biến tôi cần? Tôi thực sự thiết lập create_path=~/Desktop/site_builder/create.sh trong vỏ cha mẹ bởi vì tôi làm điều đó thường xuyên. Và tôi cần nó để gọi nguồn $ create_path [argument] để thực thi tập lệnh.

1
@JillRussek nếu các biến không được truyền vào shell con, bạn không sử dụng exportchúng. Nhưng những gì bạn mô tả thực sự rất ít ý nghĩa. Nó có vẻ ngày càng giống như một vấn đề XY . Bạn có thể muốn đăng một câu hỏi mới giải thích mục tiêu cuối cùng của bạn là gì. Tôi cá là chúng tôi có thể cung cấp cho bạn một giải pháp tốt hơn cho tất cả các nguồn tìm kiếm kỳ lạ này.
terdon

Hừm. Tôi cũng có thể cho nó một shot. Ngay bây giờ, chỉ cần sinh ra shell con từ tập lệnh thay vì từ terminal là thực hiện chính xác những gì tôi muốn. Tôi phải tìm nguồn script từ thiết bị đầu cuối để tạo môi trường ảo trong tập lệnh và pip cài đặt công cụ trong đó. Nó hoạt động như dự định bây giờ.

Nhưng bạn nói đúng, tôi đã không xuất các biến, vì tôi không biết tôi cần: D. (Tôi chưa bao giờ sinh ra một vỏ con trước đây)
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.