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


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.