ประวัติทุบตี:“ การเพิกเฉย” และ“ การลบ” การตั้งค่าความขัดแย้งกับประวัติทั่วไประหว่างเซสชัน


84

ก่อนอื่นสิ่งนี้ไม่ได้ซ้ำกับเธรดที่มีอยู่ใน SE ฉันได้อ่านสองกระทู้นี้ ( ครั้งที่ 1 , ครั้งที่ 2 ) เกี่ยวกับประวัติทุบตีที่ดีขึ้น แต่ไม่มีคำตอบใดที่ทำงานได้ดี - ฉันมาที่ Fedora 15 แล้ว

ฉันได้เพิ่มสิ่งต่อไปนี้ใน.bashrcไฟล์ในไดเรกทอรีผู้ใช้ (/ home / aahan /) และมันไม่ทำงาน ใครมีเงื่อนงำ?

HISTCONTROL=ignoredups:erasedups  # no duplicate entries
HISTSIZE=1000                     # custom history size
HISTFILESIZE=100000                 # custom history file size
shopt -s histappend                      # append to history, don't overwrite it
PROMPT_COMMAND="history -a; history -c; history -r; $PROMPT_COMMAND"  # Save and reload the history after each command finishes

ตกลงนี่คือสิ่งที่ฉันต้องการด้วยประวัติทุบตี (ลำดับความสำคัญ):

  • อย่าเก็บรายการซ้ำลบรายการที่มีอยู่
  • แชร์ประวัติกับเทอร์มินัลที่เปิดอยู่ทั้งหมดทันที
  • ผนวกประวัติเสมอไม่เขียนทับมัน
  • เก็บคำสั่งหลายบรรทัดเป็นคำสั่งเดียว (ซึ่งถูกปิดโดยค่าเริ่มต้น)
  • ขนาดประวัติเริ่มต้นและขนาดไฟล์ประวัติคืออะไร

ชน! ใคร? ไม่มีอะไรทำงาน นี่อาจเป็นปัญหากับ Fedora 15 (กับ Gnome 3 และทำงานบนเครื่องเสมือนโฮสต์ Windows) ใช่ไหม
its_me

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

1
คุณแน่ใจหรือว่าคุณกำลังใช้ bash อยู่? ( echo $SHELL) การตั้งค่าใช้งานได้หรือไม่หากคุณเรียกใช้ด้วยตนเองจากเปลือกเปิดของคุณ เห็นได้ชัดว่าเนื่องจากพวกเขาทำงานเพื่อการตั้งค่าอื่น ๆ มากมายคุณกำลังใช้ผิด และไม่มี Fedora15 / Gnome3 / bashเป็นเครื่องเสมือนมีน้อยจะทำอย่างไรกับฟังก์ชั่นที่แท้จริงของ
Caleb

@Caleb ก่อนอื่นต้องขออภัยที่กระแทกโพสต์ นอกจากนี้ฉันพยายามทำให้ดีที่สุดเพื่อให้ชัดเจนมาก ไม่ฉันไม่ได้ส่งพวกเขาไปในเปลือก ฉันเพิ่งคัดลอกวางลงใน.bashrcไฟล์ มันผิดหรือเปล่า? คุณสามารถเพิ่ม "คำตอบ" ในโพสต์นี้ด้วยคำสั่งเชลล์จริงได้หรือไม่? (โปรดทนกับ noob-ity ของฉัน)
_

1
ทุกสิ่งที่คุณเขียนในสคริปต์หรือ.bashrcคำสั่งเชลล์ที่แท้จริง สคริปต์เป็นเพียงชุดคำสั่งเชลล์ นอกจากนี้การแก้ไขที่คุณเพิ่งทำการลบexportบิตเป็นความคิดที่ไม่ดีที่ควรเก็บไว้
Caleb

คำตอบ:


119

นี่เป็นพฤติกรรมที่น่าสนใจจริง ๆ และฉันยอมรับว่าฉันประเมินคำถามต่ำเกินไปอย่างมากในตอนแรก แต่ก่อนอื่นข้อเท็จจริง:

1. ทำงานอย่างไร

ฟังก์ชันการทำงานสามารถทำได้หลายวิธีแม้ว่าแต่ละงานจะแตกต่างกันเล็กน้อย โปรดทราบว่าในแต่ละกรณีการมีประวัติ "ถ่ายโอน" ไปยังเทอร์มินัลอื่น (อัปเดต) จะต้องกดEnterที่เทอร์มินัลซึ่งเขา / เธอต้องการเรียกข้อมูลประวัติ

  • ตัวเลือกที่ 1:

    shopt -s histappend
    HISTCONTROL=ignoredups
    PROMPT_COMMAND="history -a; history -n; $PROMPT_COMMAND"
    

    มีสองข้อเสีย:

    1. ที่ล็อกอิน (เปิดเทอร์มินัล) คำสั่งสุดท้ายจากไฟล์ประวัติจะถูกอ่านสองครั้งในบัฟเฟอร์ประวัติของเทอร์มินัลปัจจุบัน
    2. บัฟเฟอร์ของเทอร์มินัลที่แตกต่างกันจะไม่ถูกซิงค์กับไฟล์ประวัติ
  • ตัวเลือก 2:

    HISTCONTROL=ignoredups
    PROMPT_COMMAND="history -a; history -c; history -r; $PROMPT_COMMAND"
    

    (ใช่ไม่จำเป็นshopt -s histappendและใช่มันต้อง history -cอยู่ตรงกลางPROMPT_COMMAND) รุ่นนี้มีข้อเสียที่สำคัญสองประการ:

    1. ไฟล์ประวัติจะต้องมีการเริ่มต้น มันจะต้องมีอย่างน้อยหนึ่งบรรทัดที่ไม่ว่างเปล่า (สามารถเป็นอะไรก็ได้)
    2. historyคำสั่งสามารถให้ผลผลิตเป็นเท็จ - ดูด้านล่าง

[แก้ไข] "และผู้ชนะคือ ... "

  • ตัวเลือก 3:

    HISTCONTROL=ignoredups:erasedups
    shopt -s histappend
    PROMPT_COMMAND="history -n; history -w; history -c; history -r; $PROMPT_COMMAND"
    

    นี่คือเท่าที่จะได้รับ มันเป็นตัวเลือกเดียวที่มีทั้งerasedupsประวัติทั่วไปและการทำงานพร้อมกัน นี่อาจเป็นทางออกสุดท้ายสำหรับปัญหาทั้งหมดของคุณอาฮาน


2. เหตุใดตัวเลือก 2 จึงไม่ทำงาน (หรือ: สิ่งที่ไม่ได้ผลตามที่คาดหมาย)

ดังที่ฉันได้กล่าวไปแล้วแต่ละวิธีการแก้ปัญหาข้างต้นนั้นทำงานแตกต่างกัน แต่การตีความเข้าใจผิดมากที่สุดของวิธีการตั้งค่าการทำงานมาจากการวิเคราะห์การส่งออกของhistoryคำสั่ง ในหลายกรณีคำสั่งสามารถให้เอาต์พุตเท็จ ทำไม? เพราะมันจะถูกดำเนินการก่อนลำดับของhistoryคำสั่งอื่น ๆ ที่มีอยู่ในPROMPT_COMMAND! อย่างไรก็ตามเมื่อใช้ตัวเลือกที่สองหรือสามผู้ใช้สามารถติดตามการเปลี่ยนแปลงของ.bash_historyเนื้อหา (ใช้watch -n1 "tail -n20 .bash_history"ตัวอย่าง) และดูว่าประวัติจริงคืออะไร

3. เหตุใดตัวเลือก 3จึงซับซ้อนมาก

ทุกอย่างอยู่ในวิธีการerasedupsทำงาน ในฐานะที่เป็นรัฐทุบตีด้วยตนเอง "( ... )erasedupsที่ทำให้เกิดริ้วรอยก่อนหน้านี้ทั้งหมดที่ตรงกับบรรทัดปัจจุบันจะถูกลบออกจากรายการประวัติก่อนที่จะสายที่ถูกบันทึกไว้" ดังนั้นนี่คือจริงๆสิ่งที่ OP ต้องการ(และไม่เพียง แต่ที่ผมเคยคิดว่าจะไม่มีซ้ำกันปรากฏในลำดับ ) นี่คือสาเหตุที่history -.คำสั่งแต่ละคำสั่งมีหรือไม่มีในPROMPT_COMMAND:

  • history -n มีที่จะมีก่อนที่จะhistory -wอ่านจาก.bash_historyคำสั่งที่บันทึกไว้จากสถานีอื่น ๆ

  • history -w มีจะต้องมีเพื่อที่จะบันทึกประวัติศาสตร์ที่จะยื่นและลบที่ซ้ำกัน

  • history -a ต้องไม่อยู่ที่นั่นแทนhistory -wเพราะจะไม่ทำให้เกิดการลบรายการที่ซ้ำกัน

  • history -cก็เป็นสิ่งจำเป็นเพราะมันป้องกัน trashing บัฟเฟอร์ประวัติหลังจากแต่ละคำสั่ง

  • และในที่สุดก็history -rเป็นสิ่งจำเป็นที่จะเรียกคืนบัฟเฟอร์ประวัติศาสตร์จากแฟ้มดังนั้นในที่สุดก็สร้างประวัติศาสตร์ที่ใช้ร่วมกันในเซสชันขั้ว


2
+1 สำหรับ "แต่การตีความที่ทำให้เข้าใจผิดมากที่สุดเกี่ยวกับวิธีการตั้งค่ามาจากการวิเคราะห์ผลลัพธ์ของคำสั่งประวัติ" ฉันคิดว่านี่เป็นแกนหลักของปัญหา OP การหักที่ยอดเยี่ยม
jasonwryan

2
ในที่สุดฉันก็เห็นประเด็นของคุณ โดย 'ซ้ำ' คุณหมายถึงอย่างอื่นมากกว่าตัวฉัน ฉันเน้นเฉพาะลำดับของคำสั่งเดียวกันเท่านั้น อัปเดตคำตอบของฉัน - ดู "ตัวเลือก 3" นอกจากนี้สำหรับกรณีของคุณเพื่อทดสอบว่าประวัติทำงานอย่างไรคุณควรใช้จริง ๆwatch "tail -n 20 .bash_history"แทนการtail -f .bash_historyใช้
rozcietrzewiacz

2
ตัวเลือก 3 เพิ่งลบประวัติทั้งหมด 100,000 บรรทัดของฉัน :( (ทุบตี 3.2.25 (1) - ปล่อยใหม่)
Felipe Alvarez

2
history -cเป็นสิ่งที่จำเป็นเนื่องจากจะป้องกันการทำลายประวัติบัฟเฟอร์หลังจากแต่ละคำสั่งทำไมการทิ้งข้อมูลนี้จึงเกิดขึ้น
Piotr Dobrogost

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

8

ในคำสั่งพรอมต์ของคุณคุณกำลังใช้-cสวิตช์ จากman bash:

-c   ล้างรายการประวัติโดยการลบรายการทั้งหมด

หากต้องการแชร์ประวัติของคุณกับเทอร์มินัลที่เปิดอยู่ทั้งหมดคุณสามารถใช้-n:

-n   อ่านบรรทัดประวัติที่ไม่ได้อ่านจากไฟล์ประวัติลงในรายการประวัติปัจจุบัน บรรทัดเหล่านี้เป็นบรรทัดต่อท้ายไฟล์ประวัติตั้งแต่เริ่มต้นเซสชันเซสชันปัจจุบัน

ขนาดเริ่มต้นยังอยู่ในคู่มือ:

HISTSIZE จำนวนคำสั่งที่ต้องจดจำในประวัติคำสั่ง (ดูประวัติด้านล่าง) ค่าเริ่มต้นคือ 500

วิธีบันทึกคำสั่งหลายบรรทัด:

cmdhistตัวเลือกเปลือกถ้าเปิดใช้งานทำให้เปลือกจะพยายามที่จะบันทึกแต่ละบรรทัดคำสั่งหลายสายในรายการประวัติศาสตร์เดียวกันเพิ่มอัฒภาคที่จำเป็นเพื่อรักษาความถูกต้องประโยค lithistตัวเลือกเปลือกทำให้เกิดเปลือกในการบันทึกคำสั่งด้วยการขึ้นบรรทัดใหม่ฝังแทนอัฒภาค

นอกจากนี้คุณไม่ควรนำหน้าคำสั่ง HIST * ด้วยexport- เป็นตัวแปรแบบ bash-only ไม่ใช่ตัวแปรด้านสิ่งแวดล้อม: HISTCONTROL=ignoredups:erasedupsเพียงพอ


ดังนั้นนี่export PROMPT_COMMAND="history -a; history -n; history -r; $PROMPT_COMMAND"ถูกต้องหรือไม่ นอกจากนี้คุณรู้หรือไม่ว่าฉันสามารถสร้างไฟล์เก็บประวัติคำสั่งหลายบรรทัดเป็นคำสั่งเดียว (ซึ่งถูกปิดโดยค่าเริ่มต้น) ??
its_me

1
ใช่. ตามหน้า man ที่ยกมาข้างต้นshopt -s cmdhistจะบันทึกหลายบรรทัด
jasonwryan

โอเคฉันลองเลย ดูเหมือนว่าHISTCONTROL=ignoredups:erasedupsจะไม่ทำงาน ฉันยังลองใช้.bashrcไฟล์นั้น (ในฟังก์ชั่นที่กำหนดเอง) มีความคิดอะไรที่อาจจะผิดหรือเปล่า? ฉันกำลังใช้งาน Fedora 15 บนเครื่องเสมือน - - โฮสต์ Windows 7
its_me

ตรวจสอบว่ามีอะไรในแฟ้มเริ่มต้นอื่น ๆ เช่น/etc/bashrc, .bash_profileฯลฯ ที่จะเอาชนะมัน
jasonwryan

ฉันไม่เห็นปัญหาใด ๆ กับ.bash_profileไฟล์ สำหรับเนื้อหาที่/etc/bashrcฉันใส่ไว้ที่นี่โปรดดู - pastebin.com/Uae6sE6s
its_me

8

นี่คือสิ่งที่ฉันมาด้วยและฉันมีความสุขกับมันจนถึง ...

alias hfix='history -n && history | sort -k2 -k1nr | uniq -f1 | sort -n | cut -c8- > ~/.tmp$$ && history -c && history -r ~/.tmp$$ && history -w && rm ~/.tmp$$'  
HISTCONTROL=ignorespace  
shopt -s histappend  
shopt -s extglob  
HISTSIZE=1000  
HISTFILESIZE=2000  
export HISTIGNORE="!(+(*\ *))"  
PROMPT_COMMAND="hfix; $PROMPT_COMMAND" 

หมายเหตุ:

  • ใช่มันมีความซับซ้อน ... แต่มันจะลบรายการที่ซ้ำกันทั้งหมดและยังรักษาเหตุการณ์ในแต่ละสถานี!
  • ฉันHISTIGNOREไม่สนใจคำสั่งทั้งหมดที่ไม่มีข้อโต้แย้ง บางคนอาจไม่ต้องการสิ่งนี้และอาจถูกทิ้งไว้


0

มันไม่ทำงานเพราะคุณลืม:

 -n   read all history lines not already read from the history file
      and append them to the history list

แต่ดูเหมือนว่าhistory -nเป็นบั๊กกี้เมื่อexport HISTCONTROL=ignoreboth:erasedupsมีผลบังคับใช้

ให้การทดสอบ:

$ PROMPT_COMMAND=
$ export HISTCONTROL=ignoreboth:erasedups
$ export HISTFILE=~/.bash_myhistory
$ HISTIGNORE='history:history -w'
$ history -c
$ history -w

ที่นี่เราเปิดการลบแบบสลับสลับประวัติเป็นไฟล์ที่กำหนดเองล้างประวัติ หลังจากคำสั่งทั้งหมดเสร็จสมบูรณ์เรามีไฟล์ประวัติที่ว่างเปล่าและหนึ่งคำสั่งที่ประวัติปัจจุบัน

$ history
$ cat ~/.bash_myhistory
$ history
$ 1  [2019-06-17 14:57:19] cat ~/.bash_myhistory

เปิด terminal ที่สองและเรียกใช้คำสั่งหกเหล่านั้นด้วย หลังจากนั้น:

$ echo "X"
$ echo "Y"
$ history -w
$ history
  1  [2019-06-17 15:00:21] echo "X"
  2  [2019-06-17 15:00:23] echo "Y"

ตอนนี้ประวัติปัจจุบันของคุณมีสองคำสั่งและไฟล์ประวัติมี:

#1560772821
echo "X"
#1560772823
echo "Y"

กลับไปที่เทอร์มินัลแรก:

$ history -n
$ history
1  [2019-06-17 14:57:19] cat ~/.bash_myhistory 
2  [2019-06-17 15:03:12] history -n

ไม่echoอ่านคำสั่งเลย เปลี่ยนเป็นเทอร์มินัลที่สองอีกครั้งและ:

$ echo "Z"
$ history -w

ตอนนี้ไฟล์ประวัติคือ:

#1560772821
echo "X"
#1560772823
echo "Y"
#1560773057
echo "Z"

สลับไปที่เทอร์มินัลแรกอีกครั้ง:

$ history -n
$ history
  1  [2019-06-17 14:57:19] cat ~/.bash_myhistory 
  2  [2019-06-17 15:03:12] history -n
echo "Z"

คุณจะเห็นว่าคำสั่งรวมecho "Z"history -n

ข้อผิดพลาดอีกอย่างหนึ่งก็เพราะคำสั่งถูกอ่านจากประวัติโดยหมายเลขคำสั่งไม่ใช่ตามเวลาคำสั่งฉันคิดว่า ฉันคาดว่าechoคำสั่งอื่น ๆ จะปรากฏที่ประวัติ


0

การลบไม่ได้ตัดแต่ง (เช่น chomp ในบางภาษา) ช่องว่างนำหน้าและต่อท้าย นี่เป็นข้อผิดพลาด การลบยังไม่ได้ลบรายการก่อนหน้าทั้งหมด

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