Bất cứ ai cũng có thể giải thích việc sử dụng lệnh exec trong shell script với các ví dụ đơn giản là gì?
Bất cứ ai cũng có thể giải thích việc sử dụng lệnh exec trong shell script với các ví dụ đơn giản là gì?
Câu trả lời:
Các exec
lệnh nhân bản tích hợp có chức năng trong kernel, có một họ trong số chúng dựa trên execve
, thường được gọi từ C.
exec
thay thế chương trình hiện tại trong quy trình hiện tại, mà không cần fork
một quy trình mới. Nó không phải là thứ bạn sẽ sử dụng trong mọi kịch bản bạn viết, nhưng nó rất hữu dụng. Đây là một số kịch bản tôi đã sử dụng nó;
Chúng tôi muốn người dùng chạy một chương trình ứng dụng cụ thể mà không cần truy cập vào trình bao. Chúng tôi có thể thay đổi chương trình đăng nhập trong / etc / passwd, nhưng có lẽ chúng tôi muốn cài đặt môi trường được sử dụng từ các tệp khởi động. Vì vậy, trong (nói) .profile
, tuyên bố cuối cùng nói một cái gì đó như:
exec appln-program
Vì vậy, bây giờ không có vỏ để quay trở lại. Ngay cả khi appln-program
gặp sự cố, người dùng cuối không thể vào vỏ, vì nó không ở đó - exec
thay thế nó.
Chúng tôi muốn sử dụng một shell khác với cái trong / etc / passwd. Có vẻ ngu ngốc, một số trang web không cho phép người dùng thay đổi vỏ đăng nhập của họ. Một trang web mà tôi biết có tất cả mọi người bắt đầu csh
và mọi người chỉ cần gọi vào .login
(tập tin khởi động csh) của họ ksh
. Trong khi nó hoạt động, nó đã đi lạccsh
quá trình đang chạy và đăng xuất là hai giai đoạn có thể gây nhầm lẫn. Vì vậy, chúng tôi đã thay đổi nó thành exec ksh
chương trình chỉ thay thế chương trình c-shell bằng korn shell và làm cho mọi thứ đơn giản hơn (có một số vấn đề khác với điều này, chẳng hạn như thực tế ksh
không phải là shell đăng nhập).
Chỉ để lưu các quy trình. Nếu chúng ta gọiprog1 -> prog2 -> prog3 -> prog4
vv và không bao giờ quay lại, thì hãy thực hiện mỗi cuộc gọi một người thực hiện. Nó tiết kiệm tài nguyên (không nhiều, thừa nhận, trừ khi lặp đi lặp lại) và làm cho việc tắt máy đơn giản hơn.
Bạn đã thấy rõ ràng exec
được sử dụng ở đâu đó, có lẽ nếu bạn cho thấy mã đang làm phiền bạn, chúng tôi có thể biện minh cho việc sử dụng nó.
Chỉnh sửa : Tôi nhận ra rằng câu trả lời của tôi ở trên là không đầy đủ. Có hai cách sử dụng exec
trong shell như ksh
và bash
- được sử dụng để mở mô tả tệp. Dưới đây là một số ví dụ:
exec 3< thisfile # open "thisfile" for reading on file descriptor 3
exec 4> thatfile # open "thatfile" for writing on file descriptor 4
exec 8<> tother # open "tother" for reading and writing on fd 8
exec 6>> other # open "other" for appending on file descriptor 6
exec 5<&0 # copy read file descriptor 0 onto file descriptor 5
exec 7>&4 # copy write file descriptor 4 onto 7
exec 3<&- # close the read file descriptor 3
exec 6>&- # close the write file descriptor 6
Lưu ý rằng khoảng cách là rất quan trọng ở đây. Nếu bạn đặt một khoảng trắng giữa số fd và ký hiệu chuyển hướng thì exec
sẽ trở về nghĩa gốc:
exec 3 < thisfile # oops, overwrite the current program with command "3"
Có một số cách bạn có thể sử dụng những cách này, trên sử dụng ksh read -u
hoặc print -u
, bash
ví dụ:
read <&3
echo stuff >&4
exec gunicorn
trả lại chính xác cho người giám sát.
exec
có thể được sử dụng để chuyển hướng:> Nếu lệnh không được xác định, bất kỳ chuyển hướng có hiệu lực trong vỏ hiện nay, và tình trạng trả lại là 0. Nếu có một lỗi chuyển hướng, tình trạng trở lại là 1. Nhưng cách làm exec
thực sự làm việc để thay đổi một mô tả tập tin? Tại sao lệnh đặc biệt này được chọn cho nhiệm vụ này? (Markdown đang thất bại ngay bây giờ?)
exec >.\logfilename.log 2>&1
&>
là một bash
phần mở rộng (xem man bash
) và ví dụ của bạn tương đương với exec >/var/log/userdata.log 2>&1
. Nói cách khác, nó chuyển hướng stdout và stderr đến tập tin đó. Các lệnh theo sau sẽ kế thừa các chuyển hướng đó trừ khi chúng được đặt lại, nhưng chúng sẽ được thực thi.
Chỉ cần tăng thêm câu trả lời được chấp nhận bằng một câu trả lời ngắn gọn thân thiện với người mới, có lẽ bạn không cần exec
.
Nếu bạn vẫn ở đây, cuộc thảo luận sau đây hy vọng sẽ tiết lộ lý do tại sao. Khi bạn chạy, nói,
sh -c 'command'
bạn chạy một sh
thể hiện, sau đó bắt đầu command
như một đứa trẻ của thể hiện đó sh
. Khi command
kết thúc, sh
ví dụ cũng kết thúc.
sh -c 'exec command'
chạy một sh
cá thể, sau đó thay thếsh
cá thể đó bằng command
nhị phân và chạy nó thay thế.
Tất nhiên, cả hai đều vô dụng trong bối cảnh hạn chế này; bạn chỉ đơn giản là muốn
command
Có một số tình huống bên lề mà bạn muốn shell đọc tệp cấu hình của nó hoặc bằng cách nào đó thiết lập môi trường như là một sự chuẩn bị để chạy command
. Đây là khá nhiều tình huống duy nhất exec command
là hữu ích.
#!/bin/sh
ENVIRONMENT=$(some complex task)
exec command
Điều này làm một số thứ để chuẩn bị môi trường để nó chứa những gì cần thiết. Khi đã xong, sh
cá thể không còn cần thiết nữa, và do đó, việc tối ưu hóa đơn giản là thay thế sh
cá thể bằng command
quy trình, thay vì sh
chạy nó như một tiến trình con và đợi nó, sau đó thoát ra ngay khi nó kết thúc.
Tương tự, nếu bạn muốn giải phóng càng nhiều tài nguyên càng tốt cho một lệnh nặng ở cuối tập lệnh shell, bạn có thể muốn exec
lệnh đó dưới dạng tối ưu hóa.
Nếu một cái gì đó buộc bạn phải chạy sh
nhưng bạn thực sự muốn chạy một cái gì đó khác, exec something else
tất nhiên là một cách giải quyết để thay thế sh
trường hợp không mong muốn (ví dụ như nếu bạn thực sự muốn chạy spiffy của riêng bạn gosh
thay vì sh
nhưng bạn không được liệt kê trong/etc/shells
để bạn có thể 'T chỉ định nó là vỏ đăng nhập của bạn).
Việc sử dụng thứ hai exec
để thao tác mô tả tập tin là một chủ đề riêng biệt. Câu trả lời được chấp nhận bao gồm điều đó độc đáo; để giữ cho nó khép kín, tôi sẽ chỉ sử dụng hướng dẫn cho bất kỳ thứ gì exec
được theo sau bởi một chuyển hướng thay vì tên lệnh.