2010-02-25 32 views
8

UPDATE: đây là một repost của How to make shell scripts robust to source being changed as they runTập lệnh shell có thể chỉ ra rằng các dòng của nó được nạp vào bộ nhớ ban đầu không?

Đây là một điều nhỏ làm tôi bực mình tất cả bây giờ và sau đó:

  1. tôi viết một kịch bản shell (bash) cho một công việc nhanh chóng và dơ bẩn
  2. Tôi chạy tập lệnh và chạy trong một thời gian khá là
  3. Trong khi chạy, tôi chỉnh sửa một vài dòng trong tập lệnh, định cấu hình nó cho một công việc khác
  4. Nhưng quá trình đầu tiên vẫn đang đọc cùng một tệp tập lệnh và được tất cả các hơi say lên.

Dường như, tập lệnh được diễn giải bằng cách tải từng dòng từ tệp vì nó là cần thiết. Có một số cách mà tôi có thể có kịch bản chỉ ra cho vỏ rằng toàn bộ tập lệnh nên được đọc vào bộ nhớ cùng một lúc? Ví dụ, các kịch bản Perl dường như làm điều này: chỉnh sửa tệp mã không ảnh hưởng đến một quá trình hiện đang diễn giải nó (vì nó được phân tích cú pháp/biên dịch ban đầu?).

Tôi hiểu rằng có nhiều cách để giải quyết vấn đề này. Ví dụ, tôi có thể thử một cái gì đó như:

cat script.sh | sh 

hoặc

sh -c "`cat script.sh`" 

... mặc dù những người có thể không hoạt động chính xác nếu các tập tin kịch bản là lớn và có giới hạn về kích thước của bộ đệm dòng và đối số dòng lệnh. Tôi cũng có thể viết một wrapper phụ trợ sao chép một tập tin kịch bản vào một tập tin tạm thời bị khóa và sau đó thực hiện nó, nhưng điều đó không có vẻ rất di động.

Vì vậy, tôi đã hy vọng cho giải pháp đơn giản nhất có liên quan đến việc sửa đổi chỉ cho tập lệnh, không phải cách thức mà nó được gọi. Tôi có thể thêm một hoặc hai dòng vào lúc bắt đầu tập lệnh không? Tôi không biết nếu một giải pháp như vậy tồn tại, nhưng tôi đoán nó có thể sử dụng biến $ 0 ...

+3

Đây là bản sao của http://stackoverflow.com/questions/2285403/how-to-make-shell-scripts-robust-to-source-being-changed-as-they-run – camh

+0

Cảm ơn, camh! Đây là hoàn hảo. – Anonymous

+0

Bạn có thể xóa tập lệnh trong khi đang chạy, để tránh chỉnh sửa. (Đây có lẽ là [ephemient] (http://stackoverflow.com/users/20713/ephemient) và [Ryan Thompson] (http://stackoverflow.com/users/125921/ryan-thompson) có nghĩa là.) Xem [ bài đăng này] (http://stackoverflow.com/questions/8335747/emacs-workflow-to-edit-bash-scripts-while-they-run) vì lý do và cách tự động hóa nó. –

Trả lời

7

Câu trả lời hay nhất tôi tìm thấy là một biến thể rất nhỏ về các giải pháp được cung cấp cho How to make shell scripts robust to source being changed as they run. Cảm ơn camh vì đã chú ý đến việc đăng lại!

#!/bin/sh 
{ 
    # Your stuff goes here 
    exit 
} 

Điều này đảm bảo rằng tất cả mã của bạn được phân tích cú pháp ban đầu; lưu ý rằng 'thoát' là rất quan trọng để đảm bảo rằng tệp không được truy cập sau này để xem liệu có các dòng bổ sung để diễn giải hay không. Ngoài ra, như đã lưu ý trong bài trước, điều này không đảm bảo rằng các tập lệnh khác được gọi bởi tập lệnh của bạn sẽ an toàn.

Cảm ơn mọi người đã trợ giúp!

2

Làm thế nào về một giải pháp để bạn chỉnh sửa nó như thế nào.

Nếu kịch bản đang chạy, trước khi chỉnh sửa nó, làm như sau:

mv script script-old 
cp script-old script 
rm script-old 

Kể từ khi giữ vỏ của các tập tin mở miễn là bạn không thay đổi các nội dung của inode mọi thứ mở sẽ làm việc okay.

Các công trình trên vì mv sẽ bảo vệ inode cũ trong khi cp sẽ tạo mã mới. Vì nội dung của một tập tin sẽ không thực sự được gỡ bỏ nếu nó được mở ra, bạn có thể loại bỏ nó ngay lập tức và nó sẽ được dọn sạch khi vỏ đóng tập tin.

+0

Cảm ơn, điều này rất hữu ích để biết! Nó khá khó khăn cho tôi để ghi nhớ, nhưng không phải là giải pháp lý tưởng nhất: nó sẽ là tốt để có một cái gì đó chứa trong tập tin kịch bản chính nó đòi hỏi toàn bộ tập tin được đọc cùng một lúc. Ví dụ: nếu nhiều nhà phát triển duy trì cùng một tập lệnh và có thể chạy trong một thời gian rất dài thì bạn cần tất cả các nhà phát triển để đảm bảo rằng họ thực hiện thủ thuật mv-cp-rm này mỗi khi họ chỉnh sửa tệp. .. – Anonymous

+1

Hơi đơn giản: 'cp script script-old; mv script-old script' –

+0

Bạn chỉ cần xóa tệp gốc. Xem nhận xét của tôi cho câu hỏi. –

2

Sử dụng trình chỉnh sửa không sửa đổi tệp hiện có và thay vào đó tạo tệp mới, sau đó thay thế tệp cũ. Ví dụ: sử dụng :set writebackup backupcopy=no trong Vim.

0

Cân nhắc tạo đường dẫn bang mới cho công việc nhanh chóng và bẩn của bạn. Nếu bạn bắt đầu tập lệnh của mình bằng: #!/usr/local/fastbash

hoặc thứ gì đó, thì bạn có thể viết trình bao bọc nhanh sử dụng một trong các phương pháp bạn đã đề cập.Đối với tính di động, người ta chỉ có thể tạo ra một liên kết tượng trưng từ fastbash để bash, hoặc có một bình luận trong kịch bản nói rằng người ta có thể thay thế fastbash bằng bash.

0

Nếu bạn sử dụng Emacs, hãy thử M-x customize-variable break-hardlink-on-save. Đặt biến này sẽ cho Emacs ghi vào một tệp tạm thời và sau đó đổi tên tệp tạm thời trên tệp gốc thay vì chỉnh sửa tệp gốc trực tiếp. Điều này sẽ cho phép cá thể đang chạy giữ phiên bản chưa được sửa đổi của nó trong khi bạn lưu phiên bản mới.

Có lẽ, các trình chỉnh sửa bán thông minh khác sẽ có các tùy chọn tương tự.

+0

Cảm ơn, đây là một mẹo tuyệt vời cho người dùng emacs, và tôi có lẽ sẽ làm cho nó trở thành thiết lập mặc định của tôi từ bây giờ trở đi. Nhưng vẫn có vấn đề bảo vệ kịch bản đang chạy của tôi khỏi bị vặn vẹo nếu ai đó chỉnh sửa nó ... – Anonymous

+0

Nó không hoạt động. Có lẽ nó có nghĩa là chỉ có nghĩa đen để phá vỡ các liên kết cứng, không phải để thay thế các tập tin với một lưu mới. –

1

Theo tài liệu bash nếu thay vì

#!/bin/bash 
body of script 

bạn cố gắng

#!/bin/bash 
script=$(cat <<'SETVAR' 
body of script 
SETVAR) 
eval "$script" 

sau đó tôi nghĩ rằng bạn sẽ có trong kinh doanh.

+0

Cảm ơn, Norman! Điều này hoạt động hoàn hảo nếu bạn đảm bảo rằng tập lệnh của bạn kết thúc bằng 'thoát'. Nó có nhược điểm, tuy nhiên, bạn mất bạn định dạng màu sắc khá in trong emacs ... – Anonymous

+0

Emacs Damn anyway! –

Các vấn đề liên quan