Tôi có thể sửa đổi tệp bash script (.sh) trong khi nó đang chạy không?


28

Giả sử tôi có một kịch bản script.sh, cần một chút thời gian để thực thi. Tôi thực hiện nó , ./script.sh. Trong khi nó đang chạy trong một cửa sổ đầu cuối, tôi sửa đổi tập tin script.sh. Điều này sẽ có bất kỳ ảnh hưởng đến quá trình đã chạy?

Sau khi sửa đổi nó, tôi thực hiện các tập tin sửa đổi, vì vậy bây giờ tôi có hai quá trình đang chạy. Cái này có ổn không


Câu trả lời:


36

Khi bạn thay đổi tập lệnh của mình, bạn thực hiện các thay đổi trên đĩa (đĩa cứng - bộ nhớ vĩnh viễn); Khi bạn thực thi tập lệnh, tập lệnh được tải vào bộ nhớ của bạn (RAM).

Vì vậy, những thay đổi mà bạn thực hiện đối với tập lệnh sẽ không ảnh hưởng đến tập lệnh đang chạy, nó sẽ chạy phiên bản bạn đã thực hiện trước khi thực hiện những thay đổi đó.

Tuy nhiên, khi bạn thực thi lại tập lệnh đã thay đổi mà không chấm dứt phiên bản đang chạy trước đó, sẽ có hai phiên bản tập lệnh - một tập lệnh có các thay đổi và tập lệnh cũ.

Được cảnh báo rằng các tài nguyên mà tập lệnh sử dụng và sửa đổi sẽ xung đột. Ví dụ: nếu bạn đang sửa đổi tệp bằng tập lệnh, tập lệnh chạy sau sẽ không thể mở tệp đó để ghi và không thực thi chính xác.

Cập nhật: Cảm ơn Người dùng đã đăng ký đã chỉ cho tôi câu trả lời tốt hơn trên Unix.stackexchange.com.

Tùy thuộc vào kích thước của tập lệnh và trình biên dịch / trình thông dịch được đề cập, tập lệnh được tải một phần / hoàn toàn. Vì vậy, nếu tập lệnh không được tải hoàn toàn, những thay đổi bạn thực hiện cho tập lệnh của mình sẽ phản ánh trên phiên bản đang chạy khi một phần của tập lệnh được tải vào bộ nhớ.

Vì vậy, không nên thay đổi tập lệnh của bạn trên đĩa hiện đang chạy cho đầu ra không thể đoán trước: Đầu tiên hãy dừng phiên bản đang chạy và sau đó sửa đổi tập lệnh của bạn và sau đó thực hiện lại tập lệnh.


11
Không phải là câu trả lời hoàn hảo, hãy đọc unix.stackexchange.com/q/121013/55673
Người dùng đã đăng ký

@registereduser: oh vâng, câu hỏi đó chỉ nhắc nhở tôi về các bài học hệ điều hành của tôi. Sẽ chỉnh sửa câu trả lời của tôi ngay khi tôi bắt tay vào máy tính để bàn của mình (trên điện thoại của tôi ngay bây giờ)
jobin

Tôi đoán rằng đối với các kịch bản ngắn sẽ không có vấn đề.
vẫy gọi

1
Khi tôi đã thử điều này với bash v3.2.48 (xem tại đây ), nó đã không đệm quá cuối dòng (và thất bại nặng nề khi tôi sửa đổi tập lệnh khi nó thực thi). Tôi vừa kiểm tra lại với bash v4.3.0 và nó đã đệm toàn bộ tập lệnh (ngắn). Vì vậy, ... tôi sẽ không dựa vào bất kỳ hành vi cụ thể nào.
Gordon Davisson

1
@RegisteredUser Không phải với tất cả các phiên bản bash - xem ví dụ tôi đã liên kết.
Gordon Davisson

4

Tôi sẽ thêm một cái gì đó mà tôi nghĩ đã không được nói trong các câu trả lời khác. Phần lớn phụ thuộc vào cách bạn chỉnh sửa tập tin. Làm echo "stuff" >filetừ shell (một ví dụ khác) thực sự sẽ ghi đè lên tệp, tôi nghĩ vậy. Nhưng nếu bạn chỉnh sửa tệp chẳng hạn emacsvà sau đó lưu, điều này sẽ không xảy ra. Thay vào đó, trình soạn thảo đổi tên tệp cũ thành một số tên dự phòng (có thể thực sự xóa bản sao lưu trước đó), sau đó viết nội dung bộ đệm đã sửa đổi của nó thành một tệp mới với tên cũ (hiện đã được xử lý) . Vì trình bao (hoặc trình thông dịch khác) đọc tập lệnh gần như chắc chắn sẽ chỉ mở tệp một lần, nên sau đó độc lập với nơi ở của tên tệp, nó chỉ tiếp tục đọc tệp đĩa vật lý (được xác định bằng số inode) được liên kết với tên tệp tại thời điểm mở. Vì vậy, ngay cả khi nó đọc tập lệnh theo khối (sẽ là giải pháp dễ nhất nếu sử dụng I / O văn bản được đệm), nó sẽ tiếp tục đọc các dòng từ phiên bản cũ của tệp, có khả năng không thay đổi khi bạn chỉnh sửa.


+1 Tôi đang sử dụng Sublime Text làm biên tập viên của mình. Bạn có biết nếu nó quá đổi tên tập tin, như thế emacsnào?
vẫy gọi

1
Tôi nghĩ rằng hầu hết các biên tập viên sẽ sử dụng sơ đồ đổi tên (ngay cả khi họ không nên giữ các phiên bản sao lưu) để tránh rủi ro nếu xảy ra sự cố trong quá trình viết, thì vẫn không có phiên bản văn bản nguyên vẹn nào. Bạn có thể kiểm tra với "ls -i" (hiển thị số inode) hành vi của trình soạn thảo của bạn là gì.
Marc van Leeuwen

1

điều này cần phải được cập nhật, câu trả lời ở trên bây giờ chỉ đúng một phần:

với phiên bản bash hiện tại, sửa đổi tập lệnh trên đĩa trong khi nó đang chạy sẽ khiến bash "cố gắng" tải các thay đổi vào bộ nhớ và thực hiện các thay đổi này trong tập lệnh đang chạy. nếu thay đổi của bạn xuất hiện sau dòng hiện đang thực thi, các dòng mới sẽ được tải và thực thi. nhưng, đây là một phỏng đoán của bash và nó có thể hiểu đúng hoặc sai.

Cách tốt hơn để làm điều này là chuỗi các hành động sau: 1) tải tập lệnh vào bộ nhớ 2) xóa tập lệnh khỏi đĩa 3) ghi tập lệnh mới vào đĩa bằng cách xóa phiên bản đĩa trước, phiên bản bộ nhớ mất liên kết với nó để khi bạn cung cấp một phiên bản mới trong bước 3, sẽ không có bất kỳ nỗ lực nào của bash để tải nội dung mới vào phiên bản bộ nhớ.


0

Câu trả lời của @ jobin nói chung là chính xác, nhưng tôi sẽ thêm một số câu trả lời khác có thể vào điểm tùy thuộc vào những gì bạn muốn làm.

Nếu bạn muốn thay đổi tập lệnh và muốn biết rằng nó an toàn, thì bạn muốn ghi vào một tệp mới, không phải tệp hiện có, Tệp mới có thể được đặt ở vị trí cũ. Viết phiên bản mới của bạn vào một tệp mới, sau đó sử dụng mvđể di chuyển nó vào vị trí trên đầu trang cũ. Các tập tin đã được thay thế vẫn tồn tại, nó chỉ không được liên kết từ thư mục. Tập lệnh đang chạy của bạn có thể tiếp tục sử dụng tập lệnh đó và khi tập lệnh đó đóng tập tin của nó, hệ thống sẽ biết rằng nó có thể dọn sạch tập tin một cách an toàn (cho dù ngay lập tức hay sau đó).

Nếu bạn muốn xử lý hành vi của kịch bản một cách nhanh chóng, bạn có một vấn đề khó khăn hơn. Tôi hy vọng bạn cần xây dựng nó thành mã của tập lệnh. Các tập lệnh Bash có thể xử lý các tín hiệu (ví dụ: có thể bắt được một cái gì đó như kill -USR1 [pid]) và sau đó một tập lệnh có thể phản hồi bằng cách tải lại một số mã. Vì vậy, có thể bạn có thể có được chức năng gần với những gì bạn muốn, nhưng không biết bạn đang theo đuổi điều gì, tôi không thấy lý do chính đáng để làm điều này và tôi nghi ngờ nếu bạn muốn làm điều gì đó phức tạp này, bạn có thể muốn một cách phức tạp hơn ngôn ngữ lập trình để làm điều đó trong.

Nếu bạn muốn hack hành vi của một tập lệnh đang chạy mà không được viết với ý nghĩ này, thì bạn đã hết may mắn. Tôi ngần ngại gọi bất kỳ nhiệm vụ lập trình nào là không thể, nhưng nếu bạn có tài nguyên và kỹ năng cho loại nhiệm vụ này, có lẽ bạn sẽ không hỏi ở đâ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.