2011-10-20 49 views
13

Làm thế nào một tập lệnh bash có thể thực thi ngay cả sau khi gặp phải một câu lệnh để xóa chính nó? Đối với ví dụ như khi tôi chạy test.sh kịch bản mà conains:Tự xóa tập lệnh bash

<--some commands--> 
rm test.sh 
<--some more commands--> 

end 

Kịch bản thực hiện đến cuối cùng trước khi xóa bản thân

+3

Khi một ứng dụng được thực hiện, mã của nó được tải vào bộ nhớ. Bạn chỉ xóa tệp trên đĩa, điều này không ảnh hưởng đến mã trong bộ nhớ. –

+1

Có lẽ toàn bộ tập lệnh được đọc vào bộ nhớ khi thực hiện và do đó các lệnh sau 'rm test.sh' vẫn tồn tại trong bộ nhớ được thực hiện. – MrMisterMan

+0

Nó không tạo bản sao trong bộ nhớ. Vì vậy, ví dụ, nếu kịch bản được sửa đổi trong khi nó đang chạy, nó sẽ thực hiện các sửa đổi. Điều này đã khiến tôi đau đầu gần đây. Ví dụ dễ thương: tập lệnh một dòng này sẽ điền vào đĩa của bạn theo thứ tự ngắn: 'cat $ 0 >> $ 0'. – Ned

Trả lời

24

Điều gì thực sự xảy ra là bash mà giữ tệp đang mở và rm sẽ không làm dừng lại đó.

Vì vậy, rm gọi hàm libc là "unlink()" sẽ xóa "liên kết" sang inode từ thư mục trong đó. "Liên kết này" trên thực tế là tên tệp cùng với số inode (bạn có thể thấy inode) số với ls -i).

Inode tồn tại miễn là chương trình mở.

Bạn có thể dễ dàng kiểm tra tuyên bố này như sau:

$ echo read a> ni 
$ bash ni 

trong khi ở một cửa sổ khác:

$ pgrep -lf bash\ ni 
31662 bash ni 
$ lsof -p 31662|grep ni 
bash 31662 wmertens 255r REG 14,2   7 12074052 /Users/wmertens/ni 
$ rm ni 
$ lsof -p 31662|grep ni 
bash 31662 wmertens 255r REG 14,2   7 12074052 /Users/wmertens/ni 

Các tập tin vẫn mở ngay cả khi bạn không còn có thể nhìn thấy nó trong ls. Vì vậy, nó không phải là bash đọc toàn bộ tập tin - nó chỉ là không thực sự đi cho đến khi bash được thực hiện với nó.

+1

Đây là lý do tại sao một chương trình cập nhật không bao giờ nên thay đổi các tập tin thực thi hiện tại, mà là hủy liên kết chúng, sau đó viết lại phiên bản mới. – curiousguy

+0

ok, nhưng điều gì xảy ra nếu tệp bị ghi đè bởi một quy trình khác? Tệp được hủy liên kết để nó được tính là "không gian trống", phải không? –

+0

Ghi đè @G_G chỉ có nghĩa là mục nhập thư mục được đặt tên theo tên tệp hiện liên kết với một inode khác. Miễn là inode ban đầu không được đóng bởi bash, nó sẽ tồn tại và sẽ được bash sử dụng. – w00t

-1

Trong thực tế, hiện tượng này là cụ thể cho vỏ (như bash), mà đọc tập tin vào bộ nhớ và sau đó thực hiện chúng.

Nếu bạn thực hiện a.bat sau: vang Yo1 del a.bat vang Yo2

Bạn nhận được các kết quả sau: C:> a.bat

C:> vang Yo1 Yo1

C:> del a.bat Không thể tìm thấy tệp bó.

Đây là mỗi sự mong đợi của bạn :-)

+1

Điều này là sai; Câu trả lời của w00t là chính xác. Tôi đã thấy lỗi cá nhân khi một tập lệnh bash được * chỉnh sửa * trong khi nó đang chạy, cho biết tệp đang được mở và đọc. –

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