อัพเดตประวัติทุบตีในเทอร์มินัลอื่นเมื่อออกจากเทอร์มินัลหนึ่ง


15

ฉันรู้ว่าคำถามนี้ไม่ปิดบังเนื่องจากมีการถามที่นี่ให้อัปเดต (และทำซ้ำที่นี่)

สิ่งที่ฉันพยายามทำให้สำเร็จนั้นต่างออกไปเล็กน้อย ฉันไม่ชอบความคิดที่จะให้ฉันเขียนไฟล์ใหม่ทุกครั้งที่lsฉันพิมพ์ ( history -a; history -c; history -r)

ฉันต้องการอัปเดตไฟล์เมื่อออก ง่ายมาก (จริง ๆ แล้วเป็นค่าเริ่มต้น) แต่คุณต้องต่อท้ายแทนที่จะเขียนใหม่:

shopt -s histappend

ตอนนี้เมื่อปิดเทอร์มินัลฉันต้องการทำให้คนอื่น ๆ ทั้งหมดที่ยังคงเปิดอยู่เพื่อรับทราบการอัพเดต

ฉันชอบทำสิ่งนี้โดยไม่ตรวจสอบผ่าน$PS1ทุกอย่างcommandที่ฉันพิมพ์ ฉันคิดว่ามันจะดีกว่าถ้าจะจับสัญญาณบางอย่าง คุณจะทำอย่างไร ถ้าไม่ได้เป็นไปได้อาจจะเป็นที่เรียบง่ายcronjob?

เราจะไขปริศนานี้ได้อย่างไร?


1
โปรดทราบว่า zsh ทำสิ่งนี้นอกกรอบ (และมีตัวเลือกมากมายในการปรับแต่งการแบ่งปันประวัติ)
Gilles 'หยุดความชั่วร้าย'

ขอบคุณ @Gilles; ตลก, ปีที่ใช้ Linux และฉันไม่เคยพยายามอะไร bashแต่ อาจถึงเวลาที่จะตรวจสอบสิ่งใหม่ ๆ เพื่อความสนุกสนาน
ดร. เบ

คำตอบ:


15

สัญญาณที่สร้างสรรค์และเกี่ยวข้องกับคุณพูด? ตกลง:

trap on_exit EXIT
trap on_usr1 USR1

on_exit() {
    history -a
    trap '' USR1
    killall -u "$USER" -USR1 bash
}

on_usr1() {
    history -n
}

โยนมันเข้า.bashrcและออก สิ่งนี้ใช้สัญญาณเพื่อบอกทุกbashขั้นตอนในการตรวจสอบรายการประวัติใหม่เมื่ออีกรายการหนึ่งออก มันแย่มาก แต่ใช้งานได้จริง


มันทำงานยังไง?

trapตั้งค่าตัวจัดการสัญญาณสำหรับสัญญาณระบบหรือเหตุการณ์ภายในของ Bash EXITเหตุการณ์ใด ๆ การยกเลิกการควบคุมของเปลือกในขณะที่USR1เป็นSIGUSR1สัญญาณความหมายที่เรากำลังจัดสรร

เมื่อใดก็ตามที่เปลือกหอยออกไปเราจะ:

  • ผนวกประวัติทั้งหมดเข้ากับไฟล์อย่างชัดเจน
  • ปิดการใช้งานSIGUSR1ตัวจัดการและทำให้เชลล์นี้ไม่สนใจสัญญาณ
  • ส่งสัญญาณไปยังbashกระบวนการที่กำลังทำงานทั้งหมดจากผู้ใช้เดียวกัน

เมื่อมีคนSIGUSR1มาถึงเรา:

  • โหลดรายการใหม่ทั้งหมดจากไฟล์ประวัติลงในรายการประวัติในหน่วยความจำของเชลล์

เนื่องจากวิธีการทุบตีสัญญาณที่จับคุณจะไม่ได้รับจริงข้อมูลประวัติศาสตร์ใหม่จนกว่าคุณจะตีEnterครั้งต่อไปดังนั้นนี้ไม่ได้ดำเนินการใด ๆ ที่ดีขึ้นในด้านหน้าที่กว่าการวางลงในhistory -n PROMPT_COMMANDมันจะบันทึกการอ่านไฟล์อย่างต่อเนื่องเมื่อไม่มีอะไรเกิดขึ้นและไม่มีการเขียนเลยจนกว่าเชลล์จะออก


อย่างไรก็ตามยังมีปัญหาอีกสองสามข้อที่นี่ แรกคือการตอบสนองเริ่มต้นที่SIGUSR1จะยุติเปลือก bashกระบวนการอื่นใด(ตัวอย่างเช่นการรันเชลล์สคริปต์) จะถูกฆ่า .bashrcไม่ได้ถูกโหลดโดยเชลล์ที่ไม่ใช่แบบโต้ตอบ แต่จะโหลดไฟล์ที่ชื่อโดยBASH_ENV : คุณสามารถตั้งค่าตัวแปรนั้นในสภาพแวดล้อมของคุณทั่วโลกให้ชี้ไปที่ไฟล์ด้วย:

trap '' USR1

ในนั้นจะไม่สนใจสัญญาณในพวกเขา (ซึ่งจะช่วยแก้ปัญหา)

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


ฉันสงสัยว่าคุณเปิดใช้งานการประทับเวลาภายใน.bashrcไฟล์หรือไม่จากนั้นมีบางอย่างที่ cronjob เข้ามาและใช้ไฟล์ดังกล่าวเป็นระยะส่งSIGUSR1ตัวอย่างข้อมูลตามที่คุณต้องการหรือไม่
forquare

มันเป็นทางออกที่เรียบร้อย แต่สำหรับความจริงแล้วกระบวนการอื่น ๆ สิ้นสุดลงเมื่อ USR1 พฤติกรรมนี้เกิดขึ้นกับ USR2 หรือไม่
ดร. เบคโก

ฉันจะเพิ่มความคิดเห็นที่สองเพราะฉันประหลาดใจ กระบวนการเชื่อมโยง TERM กับ USR1 เป็นอย่างไร ไม่ใช่ USR1 ที่ผู้ใช้จะใช้ใช่ไหม นี่คือบางส่วนหรือlinux bugไม่? ทำไมกระบวนการอื่นถึงจับ USR1 (ฉันรู้ว่ามันไม่ได้ตั้งใจที่จะกล่าวถึงที่นี่ แต่บางทีฉันอาจจะนำสิ่งนี้มาในสถานที่ที่ถูกต้อง)
Beco

พฤติกรรมเริ่มต้นของสัญญาณเกือบทั้งหมดคือการยุติ ก็ระบุไว้ใน POSIX มันไม่ใช่ข้อผิดพลาด Bash จะช่วยให้คุณระบุว่าสัญญาณจะถูกละเว้นสำหรับกระบวนการทั้งหมดของมัน แต่นั่นก็ไม่เป็นไรสำหรับวัตถุประสงค์ของเรา
Michael Homer

ขอบคุณ @MichaelHomer ข้อกำหนดนี้คุณหมายถึงทำตามBASH_ENVที่ระบุไว้ในคำตอบนี้หรือไม่? หรือคุณรู้วิธีที่เป็นมาตรฐานมากขึ้นในการปิดความชั่วร้ายนี้?
ดร. เบคโก
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.