Việc sử dụng lệnh exec trong shell script là gì?


249

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ì?


31
Các liên kết đến linux.about.com không hữu ích. Họ không làm cho nó rõ ràng từ xa việc thực thi một lệnh hoặc đường dẫn các lệnh bằng cách sử dụng 'exec' khác với việc chỉ thực hiện chúng một cách bình thường. Do đó, câu hỏi của OP "việc sử dụng exec" là gì?
Jonathan Hartley

2
Stack Overflow là một trang web cho các câu hỏi lập trình và phát triển. Câu hỏi này dường như lạc đề vì nó không liên quan đến lập trình hay phát triển. Xem những chủ đề nào tôi có thể hỏi về đây trong Trung tâm trợ giúp. Có lẽ Super User hoặc Unix & Linux Stack Exchange sẽ là một nơi tốt hơn để hỏi.
21 giờ 33 phút

Câu trả lời:


281

Các execlệ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.

execthay thế chương trình hiện tại trong quy trình hiện tại, mà không cần forkmộ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ó;

  1. 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-programgặp sự cố, người dùng cuối không thể vào vỏ, vì nó không ở đó - execthay thế nó.

  2. 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 cshvà 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 kshchươ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ế kshkhông phải là shell đăng nhập).

  3. 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 exectrong shell như kshbash- đượ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ì execsẽ 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 -uhoặc print -u, bashví dụ:

read <&3
echo stuff >&4

22
Ngoài ra còn có một cách sử dụng khác mà tôi thấy khá tiện dụng và đáng được đề cập ở đây vì nó liên quan đến các ứng dụng web python và dường như có gì đó ở giữa câu trả lời (tuyệt vời) của bạn 2 và 3. Tôi thường chạy các ứng dụng web wsgi (nói django hoặc bình) thông qua người giám sát gọi một gunicorn ứng dụng: cái sau nổi tiếng đòi hỏi khá nhiều biến môi trường, cách chạy gunicorn dễ dàng hơn và dễ bảo trì hơn từ một tập lệnh shell thiết lập mọi thứ và cuối cùng exec gunicorntrả lại chính xác cho người giám sát.
gru 8/2/2015

1
Các tài liệu làm nói rằng execcó 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 execthự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ờ?)
Ray

@Ray: tốt nhất tôi có thể làm điều đó: pubs.opengroup.org/onlinepub/009604599/utilities/exec.html . Nếu bạn cần biết làm thế nào thì hãy nhìn vào mã nguồn shell.
cdarke 20/03/2015

7
Một cách sử dụng khác: Chuyển hướng tất cả đầu ra của tập lệnh sang logfileexec >.\logfilename.log 2>&1
Hogan

1
@Carmageddon: &>là một bashphầ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.
cdarke

41

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 shthể hiện, sau đó bắt đầu commandnhư một đứa trẻ của thể hiện đó sh. Khi commandkết thúc, shví dụ cũng kết thúc.

sh -c 'exec command'

chạy một shcá thể, sau đó thay thếsh cá thể đó bằng commandnhị 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 commandlà 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, shcá 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ế shcá thể bằng commandquy trình, thay vì shchạ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 execlệ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 shnhưng bạn thực sự muốn chạy một cái gì đó khác, exec something elsetất nhiên là một cách giải quyết để thay thế shtrườ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 goshthay vì shnhư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.


2
Chống lại sự cám dỗ để gọi vỏ sò của riêng bạn bush. Tất nhiên, điều này cũng áp dụng cho bashhoặc nói chung bất kỳ shell Unix phổ biến nào; mặc dù như @ biến mất ghi chú , Bash bí mật tối ưu hóa bash -c 'command'bằng cách thực sự làm exec command.
tripleee

1
Mã thoát của shell nói chung là mã thoát của lệnh cuối cùng mà nó đã thực thi. Tất nhiên, nếu shell không chạy hoặc thực thi lệnh, trạng thái thoát của shell sẽ phản ánh điều đó với mã lỗi phù hợp.
tripleee

2
@JonathanLeffler Tôi đang cố tình ghi lại một phản đề mà tôi thấy trong các câu hỏi của người mới. Cái này đã được nhắc bởi bản sao này nhưng tôi đã thấy nó trước đây, vì vậy tôi muốn đề cập cụ thể.
tripleee

2
@JonathanLeffler Tinh chỉnh từ ngữ nhỏ; Điều này có đủ không, bạn có nghĩ? Cảm ơn vì bạn đã phản hồi.
tripleee

2
Cảm ơn - Tôi đã thêm một đoạn ngắn về tối ưu hóa này. Nó không thực sự rõ ràng với tôi nếu bạn có những phản đối khác, hoặc nếu bạn chỉ muốn giải thích mọi thứ từ một góc độ khác.
tripleee
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.