Một vỏ tương tác có thể trở thành không tương tác hoặc ngược lại?


15

Một vỏ tương tác có thể trở thành không tương tác hoặc ngược lại?

Lưu ý: Tôi đã thực hiện rất nhiều nghiên cứu về câu hỏi cơ bản, "Sự khác biệt giữa tương tác và không tương tác là gì?", Và kết quả nghiên cứu của tôi đã khiến tôi đặt câu hỏi này .

Câu hỏi này có phần mở đầu dài một phần vì nó rất quan trọng loại định nghĩa chúng ta sử dụng cho "tương tác" để trả lời nó. Một định nghĩa có thể là một nhãn tùy ý cho một bộ nhất định; nó có thể được mô tả của các thuộc tính khác nhau; hoặc nó có thể cung cấp cho bạn thông tin bạn có thể sử dụng để dự đoán hành vi và hiểu mục đích. Loại cuối cùng này chúng ta có thể gọi là "định nghĩa hành động" hoặc "định nghĩa động" và nó là hữu ích nhất.


Trong man 1p sh, định nghĩa sau đây của một vỏ tương tác được đưa ra:

   If the -i option is present, or  if  there  are  no  operands  and  the
   shells  standard  input and standard error are attached to a terminal,
   the shell is considered to be interactive.

Từ việc đề cập đến "tùy chọn -i" và sử dụng từ "toán hạng", điều này đề cập đến lời gọi của shell , không phải các thuộc tính có thể được kiểm tra trong shell đang chạy.

Trang người đàn ông Bash diễn đạt nó một chút khác biệt:

   An interactive shell is one started without  non-option  arguments  and
   without the -c option whose standard input and error are both connected
   to terminals (as determined by isatty(3)), or one started with  the  -i
   option.   PS1 is set and $- includes i if bash is interactive, allowing
   a shell script or a startup file to test this state.

Định nghĩa trong câu đầu tiên một lần nữa chỉ đề cập đến sự bắt đầu của một vỏ.

Câu thứ hai (trong bài đọc của tôi) định nghĩa các điều kiện được sử dụng làm proxy để xác định xem shell có được bắt đầu theo những cách cụ thể được xác định là làm cho nó "tương tác" hay không.

Lưu ý rằng tôi không diễn giải câu này là: "Một bash shell là tương tác khi và chỉ khi $-bao gồm 'i'." $-dường như chỉ là một chỉ báo tiện dụng, không phải là một định nghĩa về tương tác. Điều này có liên quan chủ yếu đến câu hỏi của tôi.


Cả hai điều này ( shđịnh nghĩa POSIX và Bash) là các định nghĩa cơ học cho biết trong trường hợp nào nhãn "tương tác" áp dụng cho vỏ bạn đã bắt đầu. Họ không định nghĩa hành động vì họ không đưa ra bất kỳ ý nghĩa nào của nhãn này.

Tuy nhiên, tôi thấy rằng trong suốt phần còn lại của trang Bash man được rắc các tham chiếu đến shell hoạt động theo một số cách nhất định "trừ khi đó là shell tương tác" hoặc "chỉ trong các shell tương tác, hoặc nếu tùy chọn _____ được đặt." (Có rất nhiều ví dụ và đó không phải là điểm chính của câu hỏi này.)

Vì vậy, tôi sẽ chấp nhận rằng "tương tác" chỉ là một nhãn tiện lợi cho bộ sưu tập các hành vi "tương tác" mặc định (cài đặt tùy chọn) được mô tả trong suốt phần còn lại của trang man. Bản thân nó không phải là một thuật ngữ hoặc đối tượng cơ bản; nó không có định nghĩa chính thức bên ngoài mã nguồn của shell. (Không giống như, ví dụ, các thuật ngữ "mô tả tệp mở" hoặc "quá trình dừng" dùng để chỉ các khái niệm trừu tượng được xây dựng trong thiết kế của chính kernel.)

(Mặc dù cũng được định nghĩa trong định nghĩa POSIX sh, nhưng trang người đàn ông đó [ man 1p sh] sử dụng ít hơn "trừ khi vỏ tương tác" và các câu lệnh tương tự như vậy man bash, và hầu như chỉ tập trung vào sự khác biệt về thời gian gọi, vì vậy tôi sẽ tập trung vào Bash từ thời điểm này trở đi.)


Dù sao, một số hàm ý của shell là "tương tác" chỉ có liên quan tại thời điểm gọi , chẳng hạn như các tệp được lấy bởi shell trước khi nó đọc các lệnh khác. Tuy nhiên, có những hàm ý (ít nhất là trong Bash) có liên quan bất cứ lúc nào. Do đó, phải có một cách để nói, đối với bất kỳ shell đang chạy nào , cho dù nó có tương tác hay không.

Chạy set +itrong lớp vỏ Bash tương tác khiến 'i' bị xóa khỏi nội dung của $-.

Câu hỏi là: Điều này thực sự có nghĩa là vỏ không còn tương tác?

Theo định nghĩa chính xác của Bash, không nên, vì không nơi nào trong định nghĩa được yêu cầu rằng 'tôi' phải có mặt trong $-:

   An interactive shell is one started without  non-option  arguments  and
   without the -c option whose standard input and error are both connected
   to terminals (as determined by isatty(3)), or one started with  the  -i
   option.

Việc đọc chính xác định nghĩa chính xác cũng đặt ra câu hỏi: Nếu stdin hoặc stderr của thiết bị đầu cuối tương tác được chuyển hướng để chúng không còn được kết nối với thiết bị đầu cuối, vỏ có trở thành không tương tác không?

(Dường như câu trả lời cho câu hỏi này là "không" và trang man có thể bao gồm công cụ sửa đổi: "có đầu vào và lỗi tiêu chuẩn đều được kết nối với thiết bị đầu cuối ... tại thời điểm gọi " , nhưng tôi không biết dứt khoát.)


Nếu câu trả lời là: "Không, một lớp vỏ có thể không trở thành không tương tác, cũng không phải ngược lại", sau đó là những gì dứt khoát cách để xác định nếu vỏ là tương tác?

Đặt một cách khác: Nếu có những hành vi của một "vỏ tương tác" tồn tại sau đó set +i, thì điều gì được sử dụng để xác định rằng những hành vi đó nên tiếp tục áp dụng?


Bất cứ ai cũng nghi ngờ điều đó: Có những hành vi của một cái vỏ được gọi một cách tương tác mà tồn tại sau đó set +ivà những hành vi của một cái vỏ được gọi không tương tác mà tồn tại sau đó set -i. Ví dụ, xem xét đoạn trích sau từ man bash:

COMMENTS
   In a non-interactive shell, or an interactive shell in which the inter-
   active_comments  option  to  the  shopt  builtin  is enabled (see SHELL
   BUILTIN COMMANDS below), a word beginning with # causes that  word  and
   all  remaining  characters  on that line to be ignored.  An interactive
   shell without the interactive_comments option enabled  does  not  allow
   comments.  The interactive_comments option is on by default in interac-
   tive shells.

Do đó, bằng cách bỏ đặt interactive_commentstùy chọn, chúng ta có thể thấy sự khác biệt giữa các vỏ tương tác và không tương tác. Sự tồn tại của sự khác biệt này được thể hiện bằng kịch bản sau:

#!/bin/bash

# When the testfile is run interactively,
# all three comments will produce an error
# (even the third where 'i' is not in '$-').
# When run noninteractively, NO comment will
# produce an error, though the second comment
# is run while 'i' IS in '$-'.

cat >testfile <<'EOF'
shopt interactive_comments
shopt -u interactive_comments
shopt interactive_comments
echo $-
#first test comment
set -i
echo $-
#second test comment
set +i
echo $-
#third test comment
EOF

echo 'running bash -i <testfile'
bash -i <testfile
echo 'running bash <testfile'
bash <testfile

Điều này xác nhận rằng "tương tác" và "có igiá trị $-" không tương đương.

Một thử nghiệm tương tự sử dụng ${parameter:?word}với tham số unset tạo ra kết quả tương tự, một lần nữa xác nhận rằng đó $-không phải là "nguồn sự thật" cho tính tương tác của vỏ.


Vì vậy, cuối cùng, đặc điểm 'tương tác' dứt khoát của vỏ được lưu trữ ở đâu?

Và, một vỏ tương tác có thể trở thành không tương tác hoặc ngược lại? (... Bằng cách thay đổi đặc điểm này?)


Câu trả lời:


9

Câu hỏi tôi đặt ra là tại sao mọi người lại muốn làm điều đó?

Bạn có thể vô hiệu hóa một số khía cạnh của shell tương tác như:

  • PS1= PS2= để tắt lời nhắc
  • set +m để vô hiệu hóa kiểm soát công việc
  • vô hiệu hóa lịch sử trong một số shell
  • bạn có thể dỡ bỏ zlevà tất cả các mô-đun hoàn thành trong zsh.

Nhưng nếu bạn muốn shell ngừng tương tác, thay vào đó bạn có thể làm:

. /some/file; exit

Để bảo nó lấy phần còn lại của các lệnh từ /some/file(thay thế bằng /dev/ttynếu bạn vẫn muốn đọc các lệnh từ thiết bị tty), mặc dù vẫn có một số khác biệt so với trình bao không tương tác, như đối với hành vi returnhoặc thực tế rằng nó vẫn sẽ kiểm soát công việc hoặc:

exec myshell /dev/tty

Để thay thế trình vỏ tương tác hiện tại của bạn bằng lớp vỏ không tương tác vẫn đọc các lệnh từ thiết bị tty.

Lưu ý rằng với bash 4.4, set +itrả về bash: set: +i: invalid optiongiống như trong hầu hết các shell khác.


Hoàn toàn đồng ý nó sẽ là một điều vô lý để làm. Khái niệm "tương tác" của tôi, như tôi đã đề cập, đó chỉ là một tập hợp các hành vi mặc định rất hữu ích khi bạn tương tác với trình bao của mình. Nếu bạn có thể thay đổi từng hành vi riêng lẻ và bạn thay đổi từng hành vi, thì câu hỏi "Đây có còn là vỏ tương tác không?" chỉ là ngữ nghĩa lố bịch; nó thậm chí không phải là một câu hỏi quan trọng Tuy nhiên ....
Wildcard

1
@Wildcard, nếu bạn làm exec < <(sleep infinity)trong một vỏ tương tác, bạn đã có một vỏ tương tác không tương tác lắm. Shell vẫn sẽ xem xét chính nó tương tác trong đó $-vẫn sẽ chứa i, nhưng bạn có thể không. Tôi không chắc có nhiều hơn để thảo luận về nó.
Stéphane Chazelas

2
@Wildcard, nếu shell được bắt đầu như vậy interactive, nó vẫn như vậy. Thực tế là bạn có thể làm set +itrong các phiên bản bash cũ hơn là một lỗi.
Stéphane Chazelas

1
@Wildcard, Nếu bạn nhìn vào mã nguồn của bash, có thể bạn sẽ thấy có một interactivebiến boolean toàn cầu ánh xạ tới icờ của $-. Thay đổi boolean đó sẽ không tự động thay đổi tất cả các hành vi của shell tương tác. Việc thay đổi từ tương tác sang không tương tác không được hỗ trợ.
Stéphane Chazelas

4
@Wildcard Dash chấp nhận set +ivà dừng hiển thị lời nhắc. Đây là điều mà người dùng không cần phải làm, vì vậy không có gì đáng ngạc nhiên khi hành vi phụ thuộc vào trình bao và thường là vô tình thay vì kết quả của một người thực hiện quyết định có chủ ý.
Gilles 'SO- ngừng trở nên xấu xa'
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.