Làm thế nào để lừa một lệnh nghĩ rằng đầu ra của nó sẽ đến một thiết bị đầu cuối


38

Đưa ra một lệnh thay đổi hành vi của nó khi đầu ra của nó đi đến một thiết bị đầu cuối (ví dụ: tạo ra đầu ra có màu), làm thế nào đầu ra đó có thể được chuyển hướng trong một đường ống trong khi duy trì hành vi thay đổi? Phải có một tiện ích cho điều đó, mà tôi không biết.

Một số lệnh, như grep --color=always, có các cờ tùy chọn để buộc hành vi, nhưng câu hỏi là làm thế nào để làm việc xung quanh các chương trình chỉ dựa vào việc kiểm tra bộ mô tả tệp đầu ra của chúng.

Nếu nó quan trọng, shell của tôi là bashtrên Linux.


Bạn phải biết cách lệnh kiểm tra bộ mô tả tệp đầu ra của nó và bằng cách nào đó trả về kết quả phù hợp với kết quả sẽ thấy từ thiết bị đầu cuối đầu ra.
Andrew Henle

Câu trả lời:


21

Bạn có thể nhận được những gì bạn cần bằng cách sử dụng unbuffer.

unbufferlà một tcl/ expectscript. Nhìn vào nguồn nếu bạn muốn. Cũng lưu ý phần CAVEATS ở người đàn ông.

Cũng lưu ý rằng nó không thực thi các bí danh như:

alias ls='ls --color=auto'

trừ khi người ta thêm một mánh khóe như Stéphane Chazelas đã lưu ý:

Nếu bạn thực hiện alias unbuffer='unbuffer '(lưu ý dấu cách), thì bí danh sẽ được mở rộng sau unbuffer.


Lưu ý về các bí danh được thừa nhận - nó cũng sẽ không hoạt động với bất kỳ cấu trúc shell nào khác như nội dung và hàm.
Amir

4
Nếu bạn thực hiện alias unbuffer='unbuffer '(lưu ý dấu cách), thì bí danh sẽ được mở rộng sau unbuffer.
Stéphane Chazelas

unbuffernó là! sudo apt install expect- Điều đó không rõ ràng.
loxaxs 17/03/18

22

Lịch sử của bộ công cụ

Bạn không phải là người đầu tiên muốn có một công cụ như vậy. Mọi người đã muốn các công cụ như vậy trong 30 năm. Và chúng cũng đã tồn tại gần như vậy.

Công cụ đầu tiên cho loại điều này là gói "pty" của Daniel J. Bernstein, được Rich Salz mô tả là "con dao Ginsu", mà Bernstein đã viết lại vào đầu những năm 1990 để lừa đảo nethack (sic!). Phiên bản 4 của gói "pty" được xuất bản năm 1992 tới comp.sources.unix(tập 25 số 127 đến 135). Nó vẫn có thể định vị trên World Wide Web. Paul Vixie đã mô tả nó vào thời điểm đó:

Tôi có thể nói gì? Nó cắt lát, nó thái hạt lựu, rửa chén, nó dắt chó đi dạo. Nó "chỉ hoạt động", có nghĩa là nếu bạn làm theo chỉ dẫn, bạn sẽ nhận được một gói làm việc mà không có bất kỳ nhổ tóc hoặc nghiến răng hoặc các hoạt động chuyển tiêu chuẩn khác.

Bernstein sau đó đã cập nhật điều này, đôi khi vào hoặc trước 1999-04-07, với gói "ptyget", mà ông đã thông báo:

Tôi đã kết hợp một công cụ phân bổ giả mới, ptyget. Một phiên bản alpha là tại ftp://koobera.math.uic.edu/pub/software/ptyget-0.50.tar.gz. Có một danh sách gửi thư ptyget; để tham gia, gửi một tin nhắn trống đến djb-ptyget-requ...@koobera.math.uic.edu. Tôi đã thiết kế giao diện của ptyget từ đầu. Nó nhiều mô-đun hơn pty; Giao diện pty cơ bản hiện đã được chia thành ba phần:

  • ptyget: một chương trình cấp thấp, nhỏ - chương trình setuid duy nhất trong gói - phân bổ một giả mới và chuyển nó đến chương trình bạn chọn
  • ptyspawn: một chương trình nhỏ khác chạy một tiến trình con theo giả, chờ nó thoát ra và xem các điểm dừng
  • ptyio: chương trình khác, chỉ lớn hơn một chút, di chuyển dữ liệu qua lại

Con dao Ginsu cũ ptyhiện được đánh vần ptybandage, đó là một từ đồng nghĩa với ptyget ptyio -t ptyspawn; pty -d, để đính kèm các chương trình mạng vào giả, hiện được đánh vần ptyrun, đó là một từ đồng nghĩa với ptyget ptyio ptyspawn; và nobuflà một từ đồng nghĩa cho ptyget ptyio -r ptyspawn -23x. Tôi đã tách các tính năng quản lý phiên thành một gói riêng biệt.

Gói riêng đó là gói "sess".

"ptyget", tình cờ, đáng chú ý là để minh họa một phiên bản rất sớm của, và một trong số ít các phiên bản được xuất bản của, hệ thống xây dựng "làm lại" chưa từng được công bố của Berstein. dependonlà một tiền thân rõ ràng để redo-ifchange.

Sử dụng

ptybandage

ptybandagelà những gì mọi người thường muốn trong một phiên đăng nhập. Trường hợp sử dụng chính của nó là làm cho các chương trình nhạy cảm với việc liệu đầu vào, đầu ra hoặc lỗi tiêu chuẩn của chúng được kết nối với các thiết bị đầu cuối hoạt động theo cách đó ngay cả khi chúng thực sự nằm trong các đường ống vỏ hoặc mô tả tệp tiêu chuẩn của chúng được chuyển hướng đến tệp.

Phải mất một lệnh để chạy (mà phải là một lệnh hỗ trợ toàn diện, tất nhiên) và chạy nó trong một cách mà nó nghĩ rằng nó tiêu chuẩn đầu vào, đầu ra, và lỗi được gắn vào một thiết bị đầu cuối, kết nối những thông qua để ptybandage's đầu vào tiêu chuẩn ban đầu, đầu ra, và lỗi.

Nó liên quan đến các sắc thái của việc chạy trong các vỏ điều khiển công việc, đảm bảo rằng một ký tự STOP đầu cuối không chỉ dừng lại ptybandagemà còn dừng chương trình chạy được gắn vào thiết bị đầu cuối bên trong.

ptyrun

ptyrunlà những gì mọi người thường muốn trong các máy chủ mạng TCP. Trường hợp sử dụng chính của nó là các môi trường thực thi từ xa không tự thiết lập các thiết bị đầu cuối, chạy các chương trình không hoạt động như mong muốn khi không có thiết bị đầu cuối.

Nó không mong đợi được chạy dưới lớp vỏ điều khiển công việc và nếu lệnh đang chạy nhận được tín hiệu dừng thì đơn giản là nó được khởi động lại.

Bộ công cụ có sẵn

Dru Nelson xuất bản cả "pty" phiên bản 4 và "ptyget".

Paul Jarc xuất bản một phiên bản cố định của ptyget, cố gắng đối phó với ioctls thiết bị đầu cuối dành riêng cho hệ điều hành trong bản gốc mà các hệ điều hành thực sự không còn cung cấp.

Gói nguồn nosh đi kèm với các tập lệnh ptybandangeptyruntập lệnh tương tự , sử dụng execlinecông cụ của Laurent Bercot và các lệnh quản lý thiết bị đầu cuối giả của gói nosh. Kể từ phiên bản nosh 1.23, chúng được đóng gói sẵn trong gói nosh-terminal-extend. (Các phiên bản trước đó chỉ cung cấp chúng cho những người xây dựng từ nguồn.)

Một vài ví dụ sử dụng

Jurjgen Oskam sử dụng ptybandagetrên AIX để cung cấp đầu vào từ một tài liệu ở đây cho một chương trình mở ra và đọc thiết bị đầu cuối kiểm soát của nó cho một dấu nhắc mật khẩu:

$ ptybandage dsmadmc << EOF> uit.txt
joskam
mật khẩu
phiên truy vấn
quá trình truy vấn
bỏ
EOF

Andy Bradford sử dụng ptyruntrên OpenBSD dưới daemontools và ucspi-tcp để làm cho bgplgshchương trình điều khiển bộ định tuyến tương tác có thể truy cập qua mạng trong khi làm cho nó nghĩ rằng nó đang nói chuyện với một thiết bị đầu cuối:

#! / thùng / sh
thực hiện 2> & 1
exec envuidgid rview tcpserver -vDRHl0 0 23 ptyrun / usr / bin / bgplgsh

đọc thêm


Cảm ơn bài học về lịch sử, nhưng các công cụ bạn đề xuất không có sẵn trong bản phân phối Linux hiện đại, do đó không hữu ích.
Amir

4
Có một loạt các siêu liên kết và toàn bộ một phần của câu trả lời dành cho nơi các công cụ chắc chắn nhất có sẵn.
JdeBP

1
Ý kiến ​​của bạn về điều expectgì?
CMCDragonkai

20

Bạn có thể sử dụng socat để bắt đầu quá trình của mình với một pty được kết nối và để socat kết nối đầu kia của pty với một tệp. Mà AFAIU chính xác là những gì bạn yêu cầu:

socat EXEC:"my-command",pty GOPEN:mylog.log

Phương thức này sẽ gây ra lệnh isattygọi bằng cách my-commandtrả về truevà một quá trình chỉ dựa vào đó sẽ bị đánh lừa với các mã kiểm soát đầu ra. Lưu ý rằng một số quy trình (đáng chú ý grep) cũng kiểm tra giá trị của TERMbiến môi trường, vì vậy bạn có thể cần đặt nó thành một cái gì đó hợp lý, như"xterm"


13

Ngoài ra còn có một giải pháp hay được đăng ở đây trên Super User của KarlC :

Biên dịch một thư viện chia sẻ nhỏ:

echo "int isatty(int fd) { return 1; }" | gcc -O2 -fpic -shared -ldl -o isatty.so -xc -

Sau đó nói với lệnh của bạn để tải isatty(3)ghi đè này một cách linh hoạt:

LD_PRELOAD=./isatty.so mycommand

Điều này có thể không hoạt động cho mọi lệnh ngoài kia, thậm chí có thể phá vỡ một số theo cách không mong muốn, nhưng có thể sẽ hoạt động trong hầu hết các trường hợp.


2
Đối với người dùng MacOS, bạn có thể có hành vi tương tự bằng cách sử dụngDYLD_INSERT_LIBRARIES=./isatty.so DYLD_FORCE_FLAT_NAMESPACE=y mycommand
Christopher Shroba 13/03/2017

12

Làm thế nào về việc sử dụng script(1)?

Ví dụ:

script -q -c 'ls -G' out_file

Sẽ lưu lsđầu ra out_filevới mã màu được bảo quản.


Điều này không hoạt động ở đây. Làm thế nào màu sắc được bảo quản? Có một công cụ mà tôi nên sử dụng để xuất ra out_filevới màu sắc của nó?
Kira

1
@Kira để xem các tập tin với trình tự thoát màu ANSI, tôi sử dụng less -R. Tuy nhiên, trong trường hợp này, tôi muốn đầu ra tiếp tục trong đường ống, cuối cùng đã kết thúc trong thiết bị đầu cuối của tôi. Sử dụng catđể minh họa, nó là một cái gì đó giống như script -q -c 'ls -G' /dev/null | cat, nó triệt tiêu typescripthoàn toàn tệp, chỉ để lại đầu ra của chương trình.
Amir

Để tránh tạo tệp, chỉ cần sử dụng dấu gạch ngang ( -) làm scripttệp đầu ra, ví dụ:script -q -c 'ls -G' -
Franklin Piat

0

Dựa trên câu trả lời của @ Amir , đây là tập lệnh tạo và sau đó bao gồm thư viện khi chạy:

#!/bin/bash
set -euo pipefail

function clean_up {
  trap - EXIT # Restore default handler to avoid recursion
  [[ -e "${isatty_so:-}" ]] && rm "$isatty_so"
}
# shellcheck disable=2154 ## err is referenced but not assigned
trap 'err=$?; clean_up; exit $err' EXIT HUP INT TERM

isatty_so=$(mktemp --tmpdir "$(basename "$0")".XXXXX.isatty.so)
echo "int isatty(int fd) { return 1; }" \
  | gcc -O2 -fpic -shared -ldl -o "$isatty_so" -xc -
# Allow user to SH=/bin/zsh faketty mycommand
"${SH:-$SHELL}" -c 'eval $@' - LD_PRELOAD="$isatty_so" "$@"
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.