Một lệnh exec exec Viking làm gì?


107

Tôi không hiểu lệnh bash exec. Tôi đã thấy nó được sử dụng bên trong các tập lệnh để chuyển hướng tất cả đầu ra thành một tập tin (như đã thấy trong phần này ). Nhưng tôi không hiểu làm thế nào nó hoạt động hoặc nói chung nó làm gì. Tôi đã đọc các trang người đàn ông nhưng tôi không hiểu chúng.


Bạn có quen thuộc với quá trình này không?
fkraiem

1
@fkraiem nghĩa là gì?
vẫy gọi

Xin lỗi tôi có nghĩa là "những gì". : p Nhưng câu trả lời dường như là không.
fkraiem

Nhưng thực sự kịch bản của bạn sử dụng exectheo một cách đặc biệt có thể được giải thích đơn giản hơn nhiều, tôi sẽ viết một câu trả lời.
fkraiem

Câu trả lời:


88

man bash nói:

exec [-cl] [-a name] [command [arguments]]
      If command is specified, it replaces the shell.  No new  process
      is  created.  The arguments become the arguments to command.  If
      the -l option is supplied,  the  shell  places  a  dash  at  the
      beginning  of  the  zeroth  argument passed to command.  This is
      what login(1) does.  The -c option causes command to be executed
      with  an empty environment.  If -a is supplied, the shell passes
      name as the zeroth argument to the executed command.  If command
      cannot  be  executed  for  some  reason, a non-interactive shell
      exits, unless the execfail shell option  is  enabled.   In  that
      case,  it returns failure.  An interactive shell returns failure
      if the file cannot be executed.  If command  is  not  specified,
      any  redirections  take  effect  in  the  current shell, and the
      return status is 0.  If there is a redirection error, the return
      status is 1.

Hai dòng cuối cùng là điều quan trọng: Nếu bạn tự chạy exec, không có lệnh, nó sẽ đơn giản làm cho các chuyển hướng áp dụng cho trình bao hiện tại. Bạn có thể biết rằng khi bạn chạy command > file, đầu ra của commandđược ghi filethay vì vào thiết bị đầu cuối của bạn (điều này được gọi là chuyển hướng ). Nếu bạn chạy exec > filethay thế, thì chuyển hướng áp dụng cho toàn bộ shell: Bất kỳ đầu ra nào được tạo bởi shell được ghi filethay vì cho thiết bị đầu cuối của bạn. Ví dụ ở đây

bash-3.2$ bash
bash-3.2$ exec > file
bash-3.2$ date
bash-3.2$ exit
bash-3.2$ cat file
Thu 18 Sep 2014 23:56:25 CEST

Lần đầu tiên tôi bắt đầu một bashvỏ mới . Sau đó, trong shell mới này tôi chạy exec > file, để tất cả đầu ra được chuyển hướng đến file. Thật vậy, sau đó tôi chạy datenhưng tôi không nhận được đầu ra, vì đầu ra được chuyển hướng đến file. Sau đó, tôi thoát khỏi shell của mình (để chuyển hướng không còn áp dụng nữa) và tôi thấy rằng filethực sự có chứa đầu ra của datelệnh tôi đã chạy trước đó.


42
Đây chỉ là một phần giải thích. execphục vụ để thay thế quá trình shell hiện tại bằng một lệnh, để cha mẹ đi một con đường và con sở hữu pid. Điều này không chỉ để chuyển hướng. Vui lòng thêm thông tin này
Sergiy Kolodyazhnyy

3
Theo dõi bình luận của @ SergiyKolodyazhnyy, ví dụ tôi vừa gặp đã đưa tôi đến trang này là docker-entrypoint.sh, trong đó sau khi thực hiện nhiều hành động khác nhau trên cấu hình nginx, dòng cuối cùng của tập lệnh là exec nginx <various nginx arguments>. Điều này có nghĩa là nginx tiếp quản pid script bash và bây giờ nginx là quá trình chạy chính của container chứ không phải script. Tôi cho rằng đây chỉ là sự sạch sẽ, trừ khi người khác biết lý do cụ thể hơn cho nó?
Luke Griffiths

1
@Luke Đây được gọi là "tập lệnh bao bọc". Ví dụ về điều đó cũng là gnome-terminal, mà ít nhất vào ngày 14.04 đã có một tập lệnh bao bọc để thiết lập các đối số. Và đó là mục đích duy nhất của họ, thực sự - thiết lập nghệ thuật và môi trường. Một trường hợp khác là dọn dẹp - tiêu diệt ví dụ trước của quy trình và khởi chạy quy trình mới
Sergiy Kolodyazhnyy

một execví dụ tương tự như nginxví dụ đưa ra bởi @LukeGriffiths là ~/.vnc/xstartupkịch bản mà vncserversử dụng để cấu hình một quá trình máy chủ VNC và sau đó exec gnome-sessionhoặc exec startkdevà vân vân.
Trevor Boyd Smith

@LukeGriffiths, lý do chính exectrong tập lệnh khởi động bộ chứa là vì PID 1, ENTRYPOINT của bộ chứa, có một ý nghĩa đặc biệt trong Docker. Đây là một quá trình chính nhận tín hiệu và khi nó tồn tại, container cũng thoát ra. execchỉ là một cách để shloại bỏ chuỗi lệnh này và làm cho daemon trở thành quy trình chính của container.
kkm

45

exec là một lệnh có hai hành vi rất khác biệt, tùy thuộc vào việc ít nhất một đối số được sử dụng với nó hay không có đối số nào được sử dụng.

  • Nếu ít nhất một đối số được thông qua, thì đối số đầu tiên được lấy làm tên lệnh và execcố gắng thực thi nó như một lệnh truyền các đối số còn lại, nếu có, cho lệnh đó và quản lý các chuyển hướng, nếu có.

  • Nếu lệnh được truyền dưới dạng đối số đầu tiên không tồn tại, shell hiện tại, không chỉ lệnh exec, sẽ bị lỗi.

  • Nếu lệnh tồn tại và có thể thực thi được, nó sẽ thay thế shell hiện tại. Điều đó có nghĩa là nếu execxuất hiện trong một tập lệnh, các hướng dẫn theo lệnh thực thi sẽ không bao giờ được thực thi (trừ khi execchính nó nằm trong một khung con). execkhông bao giờ trở lại Các bẫy như "EXIT" cũng sẽ không được kích hoạt.

  • Nếu không có đối số nào được thông qua, execchỉ được sử dụng để xác định lại các mô tả tệp shell hiện tại. Shell tiếp tục sau exec, không giống như trường hợp trước, nhưng đầu vào tiêu chuẩn, đầu ra, lỗi hoặc bất kỳ mô tả tệp nào đã được chuyển hướng có hiệu lực.

  • Nếu một số chuyển hướng sử dụng /dev/null, mọi đầu vào từ nó sẽ trả về EOF và mọi đầu ra cho nó sẽ bị loại bỏ.

  • Bạn có thể đóng mô tả tệp bằng cách sử dụng -làm nguồn hoặc đích, vd exec <&-. Sau đó đọc hoặc viết sẽ thất bại.

Đây là hai ví dụ:

echo foo > /tmp/bar
exec < /tmp/bar # exec has no arguments, will only affect current shell descriptors, here stdin
cat # simple command that read stdin and write it to stdout

Kịch bản lệnh này sẽ xuất "foo" dưới dạng lệnh cat, thay vì chờ nhập dữ liệu của người dùng như trong trường hợp thông thường sẽ lấy đầu vào từ tệp / tmp / bar chứa foo.

echo foo > /tmp/bar
exec wc -c < /tmp/bar # exec has two arguments, the control flow will switch to the wc command
cat

Tập lệnh này sẽ hiển thị 4(số byte trong / tmp / bar) và ngay lập tức kết thúc. Các catlệnh sẽ không được thực thi.


4
`Một số bài viết cũ không bao giờ thực sự cũ ... +1.
Cbhihe

3
Nếu một số chuyển hướng sử dụng / dev / null, bộ mô tả tệp được liên kết sẽ bị đóng. Không, nó thực sự chuyển hướng đến / từ /dev/null, vì vậy viết vẫn thành công và đọc trả về EOF. close(2)trên một fd sẽ khiến các cuộc gọi hệ thống đọc / ghi trả về lỗi và bạn làm điều đó với exec 2>&-ví dụ.
Peter Cordes

2
Hãy tự thử exec 3</dev/null; ls -l /proc/self/fd:: lưu ý rằng fd 3 sẽ được mở chỉ đọc trên / dev / null. Sau đó đóng lại exec 3<&-và bạn có thể thấy (với ls -l /proc/$$/fdmột lần nữa) rằng tiến trình shell của bạn không còn fd 3 nữa. (đóng stdin với exec <&-có thể hữu ích trong các tập lệnh, nhưng tương tác đó là đăng xuất.)
Peter Cordes

@PeterCordes Bạn hoàn toàn đúng. Trả lời cập nhật. Cảm ơn!
jlliagre

1
Câu trả lời này rất hay vì nó giải thích hai trường hợp sử dụng của execcâu trả lời được đánh giá cao nhất hiện tại chỉ nói về một trường hợp sử dụng và câu trả lời khác của g_p chỉ nói về trường hợp sử dụng khác. Và câu trả lời này là tốt đẹp và súc tích / dễ đọc cho một vấn đề phức tạp như vậy.
Trevor Boyd Smith

33

Để hiểu execbạn cần hiểu trước tiên fork. Tôi đang cố gắng để giữ cho nó ngắn.

  • Khi bạn đến ngã ba đường, bạn thường có hai lựa chọn. Các chương trình Linux đạt đến ngã ba này trên đường khi họ thực hiện một fork()cuộc gọi hệ thống.

  • Các chương trình thông thường là các lệnh hệ thống tồn tại ở dạng được biên dịch trên hệ thống của bạn. Khi một chương trình như vậy được thực thi, một quy trình mới được tạo ra. Quá trình con này có cùng môi trường với cha mẹ của nó, chỉ có số ID tiến trình là khác nhau. Thủ tục này được gọi là rèn .

  • Forking cung cấp một cách để một quy trình hiện có bắt đầu một quy trình mới. Tuy nhiên, có thể có những tình huống trong đó một tiến trình con không phải là một phần của chương trình giống như tiến trình cha mẹ. Trong trường hợp execnày được sử dụng. exec sẽ thay thế nội dung của quy trình hiện đang chạy bằng thông tin từ tệp nhị phân của chương trình.
  • Sau quá trình rèn, không gian địa chỉ của tiến trình con được ghi đè bằng dữ liệu quy trình mới. Điều này được thực hiện thông qua một cuộc gọi exec đến hệ thống.

3
bạn có thể giải thích tại sao execcó thể chuyển hướng một đầu ra tập lệnh, như trong liên kết tôi đã đăng không?
vẫy gọi

1
Tôi thấy điều này không rõ ràng "Tuy nhiên, có thể có những tình huống trong đó một tiến trình con không phải là một phần của chương trình giống như tiến trình cha mẹ"
cdosborn

6

Trong bash, nếu bạn làm help exec:

$ help exec
exec: exec [-cl] [-a name] [command [arguments ...]] [redirection ...]
    Replace the shell with the given command.

    Execute COMMAND, replacing this shell with the specified program.
    ARGUMENTS become the arguments to COMMAND.  If COMMAND is not specified,
    any redirections take effect in the current shell.

    Options:
      -a name   pass NAME as the zeroth argument to COMMAND
      -c        execute COMMAND with an empty environment
      -l        place a dash in the zeroth argument to COMMAND

    If the command cannot be executed, a non-interactive shell exits, unless
    the shell option `execfail' is set.

    Exit Status:
    Returns success unless COMMAND is not found or a redirection error occurs.

Các bit có liên quan:

If COMMAND is not specified, any redirections take effect in the current shell.

execlà một nội dung được tích hợp sẵn , tương đương với exechọ của các lệnh gọi hệ thốngG_P nói đến (và các trang mà bạn dường như đã đọc). Nó chỉ có chức năng bắt buộc POSIX ảnh hưởng đến shell hiện tại nếu không có lệnh nào được chỉ định.

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.