จะบันทึกประวัติเทอร์มินัลลงในไฟล์จากไฟล์ bash ได้อย่างไร


7

ฉันกำลังพยายามสร้างสคริปต์ทุบตีที่จะบันทึกประวัติเทอร์มินัลเป็นไฟล์ชื่อ hist.txt history > hist.txtดูเหมือนว่าการใช้จะไม่ทำงานในสคริปต์ทุบตี แต่ทำงานได้ดีเมื่อดำเนินการในบรรทัดคำสั่ง

คำแนะนำใด ๆ ที่ชื่นชมอย่างมาก

ขอบคุณจูดี้


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

6
หรือคุณต้องการที่จะส่งออกประวัติทุบตีของผู้ใช้โดยเฉพาะ? คุณสามารถอ่าน~/.bash_historyไฟล์ของผู้ใช้ได้
59 เวลา 14.16 น

1
@Arronical note ว่าสิ่งนี้จะใช้ได้ก็ต่อเมื่อผู้ใช้ใช้ Bash เป็นเชลล์ซึ่งไม่ได้เป็นแบบนั้นเสมอไป

1
@ p0llard แน่นอนฉันกระโจนด้วยข้อสันนิษฐานว่าเหมือนในสคริปต์ Bash มันจะเป็น Bash ในฐานะเชลล์ของผู้ใช้ แต่นั่นอาจไม่เป็นอย่างที่คุณพูด รายละเอียดและพื้นหลังที่ดีในคำตอบของคุณ BTW
59

คำตอบ:


11

คำตอบสั้น ๆ

เรียกใช้สคริปต์ด้วยsourceหรือ.:

source ./script_name.sh

หรือ

. ./script_name.sh

หลังเข้ากันได้กับเปลือกหอยต่างกันเล็กน้อย

คำตอบยาว

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

#!/bin/bash

cd /
ls

หากคุณเรียกใช้สิ่งนี้คุณจะได้ผลลัพธ์ดังนี้:

bin  boot  dev  etc  home  lib  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var

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

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

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

NB: sourceเป็นเชลล์ในตัวไม่ใช่โปรแกรมต่อ se - ใน Bash sourceมีความหมายเหมือนกัน.แต่ในเชลล์บางตัว.จะใช้ได้ - ฉันใช้sourceในคำตอบนี้เพราะอ่านง่ายกว่า.แต่เพื่อความเข้ากันได้สูงสุด.ควร นำมาใช้


อ่านที่น่าสนใจมาก ฉันสงสัยอยู่เสมอเกี่ยวกับคำสั่งประวัติ 'หายไป' ตอนนี้ฉันรู้แล้วว่าทำไม ขอบคุณ!
Tico

10

ก่อนอื่นโปรดทราบว่าประวัติของคุณอยู่ในไฟล์แล้ว ~/.bash_historyหากคุณกำลังใช้ทุบตีชื่อของมันมักจะ โดยเฉพาะอย่างยิ่งมันเป็นสิ่งที่คุณได้ตั้งค่าตัวแปรHISTFILEที่จะ หากคุณต้องการคัดลอกไปยังไฟล์อื่นเพียงแค่เรียกใช้cat "$HISTFILE" > hist.txt

ตอนนี้สาเหตุที่historyคำสั่งไม่ทำงานในสคริปต์ทุบตีเปลือกหอยนั่นเป็นเพราะสคริปต์ถูกเรียกใช้ในเชลล์ลูกที่ไม่ใช่แบบโต้ตอบของเซสชันเชลล์ปัจจุบันของคุณ Child shells ไม่สืบทอดสภาพแวดล้อมของพาเรนต์ทั้งหมด (ดังนั้นจึงไม่ใช่ตัวแปร set ทั้งหมด) เฉพาะตัวแปรที่ถูกเอ็กซ์พอร์ต เพื่อแสดงสคริปต์ด้านล่างจะสะท้อนค่าของตัวแปร$var:

#!/bin/bash
echo "$var"

ตอนนี้ตั้งค่า$varบางอย่างและเรียกใช้สคริปต์:

$ var="foo"
$ foo.sh
VAR: 

ถัดไปส่งออกตัวแปรก่อน:

$ var="foo"
$ export var
$ foo.sh
VAR: foo

อย่างที่คุณเห็นเมื่อตัวแปรถูกส่งออกมันจะพร้อมใช้งานสำหรับเปลือกลูก

$HISTFILENAMEที่ผมกล่าวถึงก่อนประวัติศาสตร์จะถูกเก็บไว้ในแฟ้มที่ชี้ไปตามตัวแปร เนื่องจากไม่ได้ถูกส่งออกโดยค่าเริ่มต้นจึงไม่ได้ตั้งค่าเมื่อเรียกใช้สคริปต์:

$ cat foo.sh
#!/bin/bash
echo "HISTFILE: $HISTFILE"
$ ./foo.sh
HISTFILE:
$ echo $HISTFILE
/home/terdon/.bash_history

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

ดังนั้นเพื่อให้ได้มาซึ่งประวัติคุณมีทางเลือกไม่กี่อย่าง:

  1. ที่เริ่มต้นค่าHISTFILE $HOME/.bash_historyหากคุณยังไม่ได้เปลี่ยนคุณสามารถเรียกใช้คำสั่งนี้ในสคริปต์ของคุณ:

    cat "$HOME/.bash_history" > history
  2. คุณสามารถส่ง$HISTFILEตัวแปรไปยังสคริปต์ของคุณและcat:

    #!/bin/bash
    cat "$1" > history

    บันทึกข้างต้นเป็นfoo.shและเรียกใช้ดังนี้:

    ./foo.sh "$HISTORY"
  3. ตรวจสอบให้แน่ใจว่าตัวแปรถูกส่งออก เพิ่มบรรทัดนี้ในไฟล์~/.bash_profile(ถ้ามี) หรือ~/.profile(หาก~/.bash_profileไม่มี):

    export HISTFILE

    จากนั้นออกจากระบบและเข้าสู่ระบบอีกครั้งและคุณควรจะสามารถเรียกใช้history > hist.txtจากสคริปต์ตามที่คาดไว้ นี่เป็นเพราะexport VARหมายถึง "ทำให้ $ VAR พร้อมใช้งานสำหรับเชลล์ลูก" ในแง่การปฏิบัตินี่หมายความว่าคุณค่าของHISTFILEจะได้รับการสืบทอดโดยเชลล์ที่ไม่โต้ตอบซึ่งคุณใช้เพื่อเรียกใช้สคริปต์

    ตอนนี้ในขณะที่HISTFILEจะถูกตั้งค่ามันจะไม่ถูกอ่านโดยเชลล์ที่รันสคริปต์ ดังนั้นเพื่อให้มันใช้งานได้คุณต้องอ่านมันhistory -rก่อน สคริปต์ทั้งหมดจะมีลักษณะเช่นนี้:

    $!/bin/bash
    history -r
    history > hist.txt

    หรือเพียงแค่เอ็กซ์พอร์ตด้วยตนเองก่อนรันสคริปต์:

    $ export HISTFILE

    แต่คุณจะต้องhistory -rใช้สคริปต์

  4. คุณสามารถsourceตามคำแนะนำของ@ p0llardได้

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