วิธีหลอกให้คำสั่งคิดว่าเอาต์พุตกำลังไปที่เทอร์มินัล


38

เมื่อได้รับคำสั่งที่เปลี่ยนพฤติกรรมเมื่อเอาต์พุตกำลังส่งไปยังเทอร์มินัล (เช่นสร้างเอาต์พุตสี) เอาต์พุตนั้นสามารถเปลี่ยนเส้นทางในไพพ์ไลน์ได้อย่างไรในขณะที่รักษาพฤติกรรมที่เปลี่ยนไป จะต้องมียูทิลิตี้สำหรับสิ่งที่ฉันไม่ทราบ

คำสั่งบางคำสั่งเช่นgrep --color=alwaysมีแฟล็กตัวเลือกเพื่อบังคับให้ทำงาน แต่คำถามคือวิธีการแก้ไขโปรแกรมที่ต้องอาศัยการทดสอบ descriptor ไฟล์เอาต์พุตเพียงอย่างเดียว

ถ้ามันเป็นเรื่องสำคัญเปลือกของฉันอยู่bashบน Linux


คุณต้องรู้ว่าคำสั่งทดสอบ descriptor ไฟล์เอาต์พุตของมันอย่างไรและส่งคืนผลลัพธ์ที่สอดคล้องกับผลลัพธ์ที่จะเห็นได้จากเทอร์มินัลเอาต์พุต
Andrew Henle

คำตอบ:


21

unbufferคุณอาจได้รับสิ่งที่คุณต้องการโดยใช้

unbufferเป็นtcl/ expectscript ดูแหล่งที่มาหากคุณต้องการ นอกจากนี้ให้สังเกตส่วนของถ้ำในมนุษย์ด้วย

โปรดทราบด้วยว่าจะไม่ใช้นามแฝงเช่น:

alias ls='ls --color=auto'

นอกเสียจากว่าจะมีการเพิ่มกลอุบายตามStéphane Chazelas:

ถ้าคุณทำalias unbuffer='unbuffer '(หมายเหตุพื้นที่ต่อท้าย) unbufferแล้วนามแฝงจะขยายหลังจาก


หมายเหตุเกี่ยวกับนามแฝงที่ยอมรับ - มันจะไม่ทำงานกับโครงสร้างของเชลล์อื่น ๆ เช่นบิวด์อินและฟังก์ชัน
อาเมียร์

4
ถ้าคุณทำalias unbuffer='unbuffer '(หมายเหตุพื้นที่ต่อท้าย) unbufferแล้วนามแฝงจะขยายหลังจาก
Stéphane Chazelas

unbufferมันคือ! sudo apt install expect- นั่นไม่ชัดเจน
loxaxs

22

ประวัติของชุดเครื่องมือ

คุณไม่ใช่คนแรกที่ต้องการเครื่องมือเช่นนี้ ผู้คนต้องการเครื่องมือเหล่านี้มา 30 ปีแล้ว และพวกมันมีมานานเกือบแล้วเช่นกัน

เครื่องมือที่เก่าแก่ที่สุดสำหรับสิ่งนี้คือแพ็คเกจ "pty" ของ Daniel J. Bernstein ซึ่งบรรยายโดย Rich Salz ในฐานะ "Ginsu knife" ซึ่ง Bernstein เขียนกลับไปเมื่อถึงปลายทศวรรษ 1990 เพื่อโกง nethack (sic!) แพคเกจ "pty" รุ่น 4 ได้รับการเผยแพร่ในปี 1992 ถึงcomp.sources.unix(ฉบับที่ 25 ฉบับที่ 127 ถึง 135) มันยังหาตำแหน่งได้บนเวิลด์ไวด์เว็บ Paul Vixie อธิบายในเวลา:

ฉันจะว่าอย่างไรได้? มันหั่นเป็นสี่เหลี่ยมลูกเต๋าล้างจานเดินสุนัข มัน "ใช้งานได้" ซึ่งหมายความว่าหากคุณทำตามคำแนะนำคุณจะได้รับแพ็คเกจการทำงานโดยไม่ต้องถอนผมหรือขบเขี้ยวเคี้ยวฟันหรือทำกิจกรรมพอร์ตมาตรฐานอื่น ๆ

เบิร์นสไตน์ได้อัปเดตสิ่งนี้ในภายหลัง, เมื่ออยู่บนหรือก่อน 1999-04-07, ด้วยแพ็คเกจ "ptyget" ซึ่งเขาประกาศ:

ฉันได้รวบรวมตัวจัดสรรหลอกแบบใหม่ ptyget แล้ว ftp://koobera.math.uic.edu/pub/software/ptyget-0.50.tar.gzรุ่นอัลฟาที่ มีรายชื่อผู้รับจดหมายของ ptyget; djb-ptyget-requ...@koobera.math.uic.eduที่จะเข้าร่วมส่งข้อความว่างเปล่า ฉันออกแบบอินเตอร์เฟสของ ptyget ตั้งแต่เริ่มต้น มันเป็นแบบแยกส่วนมากกว่า pty; ส่วนต่อประสาน pty พื้นฐานตอนนี้ถูกแบ่งออกเป็นสามส่วน:

  • ptyget: โปรแกรมขนาดเล็กระดับต่ำ - โปรแกรม setuid เดียวในแพ็คเกจ - ที่จัดสรร pseudo-tty ใหม่และส่งไปยังโปรแกรมที่คุณเลือก
  • ptyspawn: โปรแกรมขนาดเล็กอีกตัวที่ใช้กระบวนการเด็กภายใต้ระบบหลอกรอให้มันออกจากระบบและเฝ้าดูการหยุด
  • ptyio: อีกโปรแกรมที่ใหญ่กว่าเพียงเล็กน้อยเท่านั้นที่เคลื่อนย้ายข้อมูลไปมา

ptyตอนนี้มีด Ginsu เก่าสะกดptybandageซึ่งเป็นคำพ้องความหมายสำหรับptyget ptyio -t ptyspawn; pty -dสำหรับการแนบโปรแกรมเครือข่ายไปยัง pseudo-ttys จะถูกสะกดptyrunซึ่งเป็นคำพ้องความหมายสำหรับptyget ptyio ptyspawn; และเป็นคำพ้องสำหรับnobuf ptyget ptyio -r ptyspawn -23xฉันได้แยกฟีเจอร์การจัดการเซสชันออกเป็นแพ็คเกจแยกต่างหาก

แพ็คเกจที่แยกต่างหากนั้นคือแพ็คเกจ "sess"

"ptyget" เป็นที่น่าสังเกตว่าเป็นตัวอย่างรุ่นแรก ๆ และเป็นหนึ่งในไม่กี่กรณีที่เผยแพร่โดย Berstein ซึ่งเป็นเจ้าของระบบสร้าง "redo" ที่ไม่เคยตีพิมพ์ เป็นสารตั้งต้นที่ชัดเจนในการdependonredo-ifchange

การใช้

ptybandage

ptybandageเป็นสิ่งที่ผู้คนมักต้องการในเซสชันการเข้าสู่ระบบ กรณีการใช้งานหลักคือการสร้างโปรแกรมที่มีความอ่อนไหวต่อว่าอินพุตมาตรฐานเอาต์พุตหรือข้อผิดพลาดถูกเชื่อมต่อกับเทอร์มินัลทำงานด้วยวิธีนั้นแม้ว่าในความเป็นจริงแล้วในเชลล์ไพพ์ไลน์หรือมีการเปลี่ยนเส้นทางไฟล์มาตรฐาน

มันต้องใช้คำสั่งเพื่อเรียกใช้ (ซึ่งจะต้องมีคำสั่งภายนอกที่เหมาะสมของหลักสูตร) และทำงานในลักษณะที่จะคิดว่านำเข้าส่งออกและข้อผิดพลาดมาตรฐานของมันจะแนบไปกับสถานีที่เชื่อมต่อผู้ที่ผ่านไปptybandageมา อินพุตมาตรฐานเอาต์พุตและข้อผิดพลาดมาตรฐาน

มันเกี่ยวข้องกับความแตกต่างของการทำงานภายใต้เชลล์ควบคุมงานตรวจสอบให้แน่ใจว่าอักขระ STOP เทอร์มินัลไม่เพียงหยุดptybandageแต่ยังหยุดโปรแกรมที่รันอยู่ที่เชื่อมต่อกับเทอร์มินัลภายใน

ptyrun

ptyrunเป็นสิ่งที่คนทั่วไปต้องการในเซิร์ฟเวอร์เครือข่าย TCP กรณีการใช้งานหลักคือสภาพแวดล้อมการดำเนินการทางไกลที่ยังไม่ได้ตั้งค่าเทอร์มินัลตัวเองรันโปรแกรมที่ไม่ทำงานตามที่ต้องการเมื่อไม่มีเทอร์มินัล

มันไม่ได้คาดหวังว่าจะทำงานภายใต้เชลล์ควบคุมงานและถ้าคำสั่งที่กำลังเรียกใช้ได้รับสัญญาณหยุดมันก็เริ่มต้นใหม่

ชุดเครื่องมือที่มีอยู่

Dru Nelson เผยแพร่ทั้ง "pty" รุ่น 4 และ "ptyget"

Paul Jarc เผยแพร่ ptyget รุ่นคงที่ซึ่งพยายามจัดการกับอุปกรณ์หลอกระบบเทอร์มินัล ioctls ในระบบปฏิบัติการเฉพาะในต้นฉบับที่ระบบปฏิบัติการไม่ได้ให้บริการอีกต่อไป

ซอร์สแพ็กเกจ nosh มาพร้อมกับ workalike ptybandangeและptyrunสคริปต์ซึ่งใช้execlineเครื่องมือของ Laurent Bercot และคำสั่งการจัดการ pseudo-terminal ของ nosh แพ็กเกจเอง ในฐานะของ nosh เวอร์ชัน 1.23 สิ่งเหล่านี้มีอยู่ในแพ็คเกจก่อนบรรจุในแพ็คเกจ nosh-terminal-extras (เวอร์ชันก่อนหน้านี้มอบให้เฉพาะกับคนที่สร้างขึ้นจากแหล่งที่มา)

ตัวอย่างบางส่วนใช้

Jurjgen Oskam ที่ใช้ptybandageบน AIXเพื่อฟีดอินพุตจากเอกสารที่นี่ไปยังโปรแกรมที่ explicity เปิดขึ้นและอ่านเทอร์มินัลการควบคุมสำหรับพร้อมต์รหัสผ่าน:

$ ptybandage dsmadmc << EOF> uit.txt
joskam
รหัสผ่าน
เซสชั่นแบบสอบถาม
กระบวนการค้นหา
เลิก
EOF

Andy Bradford ใช้งานptyrunบน OpenBSDภายใต้ daemontools และ ucspi-tcp เพื่อให้bgplgshโปรแกรมควบคุมเราเตอร์แบบโต้ตอบสามารถเข้าถึงได้ผ่านเครือข่ายในขณะที่คิดว่ามันกำลังพูดกับเทอร์มินัล:

#! / bin / ดวลจุดโทษ
exec 2> & 1
exec envuidgid rviews tcpserver -vDRHl0 0 23 ptyrun / usr / bin / bgplgsh

อ่านเพิ่มเติม

  • Daniel J. Bernstein (1992-02-19) v25i127: ทั่วไปอินเตอร์เฟซกับอุปกรณ์หลอก comp.sources.unix 25 (127)
  • Daniel J. Bernstein (1991-10-04) ความรู้เบื้องต้นเกี่ยวกับการจัดการเซสชั่น Bernstein บน TTYs JdeBP
  • Paul Jarc ptyget ซอฟต์แวร์ของ Paul Jarc
  • Jonathan de Boyne Pollard (2016) แดเนียลเจ Bernstein ของชุดเครื่องมือ โปรแกรม
  • Dru Nelson drudru / pty4 GitHub
  • Dru Nelson drudru / ptyget GitHub
  • Laurent Bercot เอ็กซีคิวต์ ซอฟต์แวร์.
  • Jonathan de Boyne Pollard (2016) โปรแกรมแดเนียลเจ Bernstein ของทั้งหมดในที่เดียว โปรแกรม
  • Jonathan de Boyne Pollard (2014) แพคเกจ Nosh โปรแกรม
  • Jonathan de Boyne Pollard (2012) แนะนำให้รู้จักกับ redoคำตอบที่ได้รับบ่อย
  • Reyk Floeter bgplgsh. 8. หน้าคู่มือ OpenBSD

ขอบคุณสำหรับบทเรียนในประวัติศาสตร์ แต่เครื่องมือที่คุณแนะนำไม่พร้อมใช้งานในการกระจาย Linux ที่ทันสมัยจึงไม่มีประโยชน์
อาเมียร์

4
มีการเชื่อมโยงหลายมิติและคำตอบทั้งหมดซึ่งอุทิศให้กับเครื่องมือที่มีให้ใช้มากที่สุด
JdeBP

1
คุณมีความคิดเห็นexpectอย่างไร?
CMCDragonkai

20

คุณสามารถใช้socatเพื่อเริ่มกระบวนการของคุณด้วยpty ที่เชื่อมต่อและรับ socat เพื่อเชื่อมต่อปลายอีกด้านของ pty กับไฟล์ AFAIU ใดที่ตรงกับที่คุณถาม:

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

วิธีนี้จะทำให้เกิดการisattyเรียกโดยmy-commandการกลับมาtrueและกระบวนการที่อาศัยเพียงว่าจะถูกหลอกไปที่รหัสควบคุมการส่งออก โปรดทราบว่ากระบวนการบางอย่าง (โดยเฉพาะgrep) ตรวจสอบค่าของTERMตัวแปรสภาพแวดล้อมด้วยดังนั้นคุณอาจจำเป็นต้องตั้งค่าเป็นสิ่งที่สมเหตุสมผลเช่น"xterm"


13

นอกจากนี้ยังมีทางออกที่ดีที่โพสต์ไว้ที่นี่บน Super UserโดยKarlC :

รวบรวมห้องสมุดสาธารณะขนาดเล็ก:

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

จากนั้นบอกให้คำสั่งของคุณโหลดการisatty(3)แทนที่นี้แบบไดนามิก:

LD_PRELOAD=./isatty.so mycommand

สิ่งนี้อาจไม่ได้ผลสำหรับทุกคำสั่งที่นั่นแม้อาจทำลายบางอย่างด้วยวิธีที่ไม่คาดคิด แต่อาจทำงานได้ในกรณีส่วนใหญ่


2
สำหรับผู้ใช้ MacOS คุณสามารถรับพฤติกรรมเดียวกันได้โดยใช้DYLD_INSERT_LIBRARIES=./isatty.so DYLD_FORCE_FLAT_NAMESPACE=y mycommand
Christopher Shroba

12

วิธีการเกี่ยวกับการใช้งานscript(1)?

ตัวอย่างเช่น:

script -q -c 'ls -G' out_file

จะบันทึกlsผลลัพธ์ไปout_fileพร้อมกับรหัสสีที่เก็บรักษาไว้


สิ่งนี้ไม่ทำงานที่นี่ สีจะถูกรักษาไว้อย่างไร? มีเครื่องมือที่ฉันควรใช้ในการแสดงผลout_fileด้วยสีหรือไม่?
คิระ

1
@Kira สำหรับการดูไฟล์ที่มีลำดับหนี ANSI less -Rสีผมใช้ ในกรณีนี้ฉันต้องการให้ผลลัพธ์ต่อไปในไปป์ไลน์ซึ่งท้ายที่สุดก็กลายเป็นเทอร์มินัลของฉัน การใช้catภาพประกอบเป็นสิ่งscript -q -c 'ls -G' /dev/null | catที่ยับยั้งtypescriptไฟล์ทั้งหมดโดยไม่เหลือเอาท์พุทของโปรแกรม
อาเมียร์

เพื่อหลีกเลี่ยงการสร้างไฟล์เพียงใช้ dash ( -) เป็นscriptไฟล์เอาต์พุตสำหรับตัวอย่าง:script -q -c 'ls -G' -
Franklin Piat

0

ตามคำตอบของ @ Amirนี่คือสคริปต์ที่สร้างและรวมไลบรารีที่รันไทม์:

#!/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" "$@"
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.