Pertahankan riwayat bash di beberapa terminal windows


525

Saya secara konsisten memiliki lebih dari satu terminal terbuka. Di mana saja dari dua hingga sepuluh, melakukan berbagai bit dan bobs. Sekarang katakanlah saya me-restart dan membuka terminal lain. Beberapa mengingat hal-hal tertentu, beberapa lupa.

Saya ingin sejarah yang:

  • Ingat semuanya dari setiap terminal
  • Dapat diakses secara instan dari setiap terminal (mis. Jika saya lsdalam satu terminal , pindah ke terminal lain yang sudah berjalan dan kemudian tekan naik, lsmuncul)
  • Tidak lupa perintah jika ada spasi di depan perintah.

Adakah yang bisa saya lakukan untuk membuat bash bekerja lebih seperti itu?


57
Saya dapat melihat keuntungan dari itu, tetapi secara pribadi saya akan BENCI itu di shell saya. Saya biasanya membiarkan 3 atau 4 tab terbuka di terminal saya untuk penggunaan yang sangat spesifik: satu untuk menjalankan 'make', satu dengan vi, satu untuk menjalankan hal-hal, dll. Jadi ketika saya kompilasi, saya pergi ke tab 1, tekan ke atas dan 'buat 'Muncul, dan sebagainya. Ini sangat produktif bagi saya. Jadi jika tiba-tiba saya pergi ke tab 'make' saya dan tekan dan beberapa perintah grep acak muncul, saya akan benar-benar kesal! Hanya sebuah catatan pribadi
axel_c

4
@ Maxel_c itu cukup benar. Saya tidak bisa memikirkan cara yang cerdas untuk melakukannya di mana terminal yang ada hanya melihat sejarah mereka sendiri tetapi yang baru melihat daftar perintah yang secara kronologis akurat.
Oli

8
@Oli menulis, "Saya tidak bisa memikirkan cara yang cerdas untuk melakukannya di mana terminal yang ada hanya melihat sejarah mereka sendiri tetapi yang baru melihat daftar perintah yang secara kronologis akurat." Bagaimana (belum dicoba): export PROMPT_COMMAND="history -a; $PROMPT_COMMAND". Kerang yang ada akan menambahkan setiap perintah ke file riwayat untuk dilihat kerang baru, tetapi hanya menampilkan sejarahnya sendiri.
Chris Page

2
Apakah Anda ingin semua riwayat disimpan secara terpisah atau semua digabung menjadi satu file riwayat?
kbyrd

3
Jawaban singkatnya adalah: itu tidak dimaksudkan oleh pengembang bash. Solusi berdasarkan pembilasan kemudian membaca kembali sejarah mungkin berhasil, tetapi waspadalah terhadap Shlemiel The Painter . Dengan kata sederhana: jumlah pekerjaan pemrosesan antara setiap perintah sebanding dengan ukuran riwayat.
Stéphane Gourichon

Jawaban:


328

Tambahkan berikut ini ke ~ / .bashrc

# Avoid duplicates
export HISTCONTROL=ignoredups:erasedups  
# When the shell exits, append to the history file instead of overwriting it
shopt -s histappend

# After each command, append to the history file and reread it
export PROMPT_COMMAND="${PROMPT_COMMAND:+$PROMPT_COMMAND$'\n'}history -a; history -c; history -r"

20
Masalah dengan solusi PROMPT_COMMAND ini adalah bahwa angka untuk setiap item histori berubah setelah setiap perintah :(. Misalnya jika Anda mengetik histori dan 1) ls 2) rm, maka Anda melakukannya! 1 untuk mengulangi 1, nomor histori mungkin berubah dan mungkin menjalankan perintah rm ...
Chris Kimpton

2
Ketika saya melakukan ini, terminal yang sudah terbuka lainnya tidak memiliki perintah masuk lalu ketika saya menekan 'Up' sampai setelah saya mengeluarkan perintah pada yang terminal - yang ini diharapkan? Jika demikian, adakah cara untuk benar-benar mengubah riwayat terminal lain secara instan?
Suan

7
@Suan, ini sepertinya benar bagi saya berdasarkan pada perintah. Saya menemukan bahwa kita dapat mengeluarkan perintah nol (cukup tekan tombol enter) untuk mendapatkan histori yang diperbarui.
bijak

3
Sebenarnya history -a(...) tidak memicu menghapus duplikat menurut ini jawaban atas pertanyaan sejarah Bash: “ignoredups” dan “erasedups” pengaturan konflik dengan sejarah umum di sesi . Jawaban ini juga memberikan urutan history -<option>perintah yang berfungsi dengan HISTCONTROL=ignoredups:erasedupspengaturan.
Piotr Dobrogost

23
Tidak ada alasan untuk exportitu HISTCONTROLdan PROMPT_COMMANDvariabel: Anda mendefinisikan mereka dalam .bashrcsehingga mereka akan ditentukan di setiap shell (bahkan dalam yang non-interaktif, yang juga boros).
dolmen

248

Jadi, ini semua yang berhubungan dengan sejarah saya .bashrc:

export HISTCONTROL=ignoredups:erasedups  # no duplicate entries
export HISTSIZE=100000                   # big big history
export HISTFILESIZE=100000               # big big history
shopt -s histappend                      # append to history, don't overwrite it

# Save and reload the history after each command finishes
export PROMPT_COMMAND="history -a; history -c; history -r; $PROMPT_COMMAND"

Diuji dengan bash 3.2.17 pada Mac OS X 10.5, bash 4.1.7 pada 10.6.


3
Hmm .. Ini membunuh kemampuan untuk menggunakan $! 34, karena nomor perintah berubah setiap prompt. Apakah ada solusinya @Davide @Schof @kch?

5
Gunakan ini untuk mendapatkan sejarah tanpa batas: bash sejarah abadi . NAMUN, ini gratis untuk kode di atas, karena tidak akan dimuat ulang secara otomatis.

7
FYI Tidak ada solusi yang disebutkan di sini yang dapat memecahkan masalah berikut. Saya memiliki dua jendela shell A dan B. Di jendela shell A, saya berlari sleep 9999, dan (tanpa menunggu waktu tidur selesai) di jendela shell B, saya ingin dapat melihat sleep 9999di bash history.
Poin

1
@ Poin Saya juga bertujuan untuk perilaku hidup, tetapi kemudian saya menyadari bahwa lebih mudah untuk memiliki sejarah spesifik terminal yang membuat bekerja pada hal-hal yang berbeda di terminal yang berbeda lebih mudah. Saya menemukan ini sangat berguna: stackoverflow.com/questions/338285/#answer-7449399 Berdasarkan hal itu, saya membuat sendiri nama alias hrefyang menyegarkan sejarah terminal saya saat ini secara instan dan membersihkan file histori dalam proses. Setiap kali saya membuka terminal baru, pembersihan / sinkronisasi itu dijalankan di file bashrc saya sehingga terminal baru memiliki sejarah terbaru. Saya menggunakan itu bersama denganhistory -a
trusktr

6
Tidak ada alasan untuk exportvariabel: Anda mendefinisikan mereka .bashrcsehingga mereka akan didefinisikan di setiap shell (bahkan yang non-interaktif, yang juga boros)
dolmen

117

Ini adalah upaya saya untuk berbagi riwayat sesi Bash. Ini akan memungkinkan pembagian riwayat antara sesi bash dengan cara agar penghitung sejarah tidak ikut campur dan ekspansi riwayat seperti itu !numberakan berfungsi (dengan beberapa kendala).

Menggunakan Bash versi 4.1.5 di bawah Ubuntu 10.04 LTS (Lucid Lynx).

HISTSIZE=9000
HISTFILESIZE=$HISTSIZE
HISTCONTROL=ignorespace:ignoredups

_bash_history_sync() {
    builtin history -a         #1
    HISTFILESIZE=$HISTSIZE     #2
    builtin history -c         #3
    builtin history -r         #4
}

history() {                  #5
    _bash_history_sync
    builtin history "$@"
}

PROMPT_COMMAND=_bash_history_sync

Penjelasan:

  1. Tambahkan baris yang baru saja dimasukkan ke $HISTFILE(standarnya adalah .bash_history). Ini akan menyebabkan $HISTFILEpertumbuhan satu baris.

  2. Mengatur variabel khusus $HISTFILESIZEke beberapa nilai akan menyebabkan Bash memotong $HISTFILEtidak lebih dari $HISTFILESIZEgaris dengan menghapus entri terlama.

  3. Kosongkan riwayat sesi lari. Ini akan mengurangi penghitung riwayat dengan jumlah $HISTSIZE.

  4. Baca konten $HISTFILEdan masukkan ke riwayat sesi berjalan saat ini. ini akan meningkatkan penghitung sejarah dengan jumlah baris dalam $HISTFILE. Perhatikan bahwa jumlah baris $HISTFILEbelum tentu $HISTFILESIZE.

  5. The history()Fungsi menimpa sejarah builtin memastikan bahwa sejarah disinkronisasikan sebelum ditampilkan. Ini diperlukan untuk ekspansi sejarah dengan angka (lebih lanjut tentang ini nanti).

Penjelasan lebih lanjut:

  • Langkah 1 memastikan bahwa perintah dari sesi berjalan saat ini akan ditulis ke file riwayat global.

  • Langkah 4 memastikan bahwa perintah dari sesi lain bisa dibaca ke riwayat sesi saat ini.

  • Karena langkah 4 akan meningkatkan penghitung sejarah, kita perlu mengurangi penghitung dengan beberapa cara. Ini dilakukan pada langkah 3.

  • Di langkah 3 penghitung sejarah dikurangi oleh $HISTSIZE. Pada langkah 4 penghitung sejarah dinaikkan oleh jumlah baris di $HISTFILE. Pada langkah 2 kami memastikan bahwa jumlah baris $HISTFILEpersis $HISTSIZE(ini artinya $HISTFILESIZEharus sama dengan $HISTSIZE).

Tentang kendala ekspansi sejarah:

Saat menggunakan ekspansi riwayat dengan angka, Anda harus selalu mencari nomornya segera sebelum menggunakannya. Itu berarti tidak ada tampilan bash prompt antara mencari nomor dan menggunakannya. Itu biasanya berarti no enter dan no ctrl + c.

Secara umum, setelah Anda memiliki lebih dari satu sesi Bash, tidak ada jaminan apa pun bahwa ekspansi riwayat dengan angka akan mempertahankan nilainya di antara dua tampilan Bash prompt. Karena ketika PROMPT_COMMANDdijalankan, riwayat dari semua sesi Bash lainnya terintegrasi dalam riwayat sesi saat ini. Jika ada sesi bash lain yang memiliki perintah baru, maka nomor riwayat sesi saat ini akan berbeda.

Saya menemukan batasan ini masuk akal. Lagi pula saya harus mencari nomornya karena saya tidak dapat mengingat angka sejarah yang berubah-ubah.

Biasanya saya menggunakan ekspansi sejarah dengan nomor seperti ini

$ history | grep something #note number
$ !number

Saya sarankan menggunakan opsi Bash berikut.

## reedit a history substitution line if it failed
shopt -s histreedit
## edit a recalled history line before executing
shopt -s histverify

Bug aneh:

Menjalankan perintah histori yang disalurkan ke apa saja akan menghasilkan perintah yang terdaftar dalam histori dua kali. Sebagai contoh:

$ history | head
$ history | tail
$ history | grep foo
$ history | true
$ history | false

Semua akan terdaftar dalam sejarah dua kali. Saya tidak tahu kenapa.

Gagasan untuk peningkatan:

  • Ubah fungsi _bash_history_sync()agar tidak dieksekusi setiap saat. Sebagai contoh, ia tidak boleh dijalankan setelah CTRL+Cdiminta. Saya sering menggunakan CTRL+Cuntuk membuang baris perintah yang panjang ketika saya memutuskan bahwa saya tidak ingin mengeksekusi baris itu. Terkadang saya harus menggunakan CTRL+Cuntuk menghentikan skrip penyelesaian Bash.

  • Perintah dari sesi saat ini harus selalu menjadi yang terbaru dalam sejarah sesi saat ini. Ini juga akan memiliki efek samping bahwa nomor sejarah yang diberikan menyimpan nilainya untuk entri riwayat dari sesi ini.


1
Mengapa tidak "history -n" (memuat ulang baris yang belum dimuat) alih-alih "history -c; history -r"?
Graham

@ Graham: Saya tidak ingin menggunakan history -nkarena itu mengacaukan counter sejarah. Juga, saya menemukan history -nterlalu tidak dapat diandalkan.
lesmana

1
Satu kelemahan: Perintah dengan string multi-line biasanya masih dipertahankan di sesi saat ini. Dengan trik ini, mereka dibagi menjadi garis-garis individu secara instan. Menggunakan -n untuk -c -r tidak membantu, begitu juga cmdhist atau lithist. Saya tidak berpikir ada solusi saat ini.
Jo Liss

24
Setelah mencoba ini sebentar, saya benar-benar menemukan bahwa hanya menjalankan history -a, tanpa -cdan -r, lebih baik kegunaan-bijaksana (meskipun bukan itu pertanyaannya). Ini berarti perintah yang Anda jalankan tersedia secara instan di shell baru bahkan sebelum keluar dari shell saat ini, tetapi tidak di shell yang berjalan bersamaan. Dengan cara ini Arrow-Up masih selalu memilih perintah yang dijalankan terakhir dari sesi saat ini , yang menurut saya jauh lebih membingungkan.
Jo Liss

jawaban yang luar biasa bagus, ini bekerja andal tidak seperti "sejarah -a; sejarah -n" yang lebih umum
RichVel

42

Saya tidak mengetahui cara apa pun menggunakan bash. Tapi itu salah satu fitur paling populer zsh.
Secara pribadi saya lebih suka zshlebih bashjadi saya sarankan mencoba.

Inilah bagian dari saya .zshrcyang berkaitan dengan sejarah:

SAVEHIST=10000 # Number of entries
HISTSIZE=10000
HISTFILE=~/.zsh/history # File
setopt APPEND_HISTORY # Don't erase history
setopt EXTENDED_HISTORY # Add additional data to history like timestamp
setopt INC_APPEND_HISTORY # Add immediately
setopt HIST_FIND_NO_DUPS # Don't show duplicates in search
setopt HIST_IGNORE_SPACE # Don't preserve spaces. You may want to turn it off
setopt NO_HIST_BEEP # Don't beep
setopt SHARE_HISTORY # Share history between session/terminals


16

Untuk melakukan ini, Anda harus menambahkan dua baris ke ~/.bashrc:

shopt -s histappend
PROMPT_COMMAND="history -a;history -c;history -r;$PROMPT_COMMAND"

Dari man bash:

Jika opsi histappend shell diaktifkan (lihat deskripsi shopt di bawah SHELL BUILTIN COMMANDS di bawah), baris ditambahkan ke file histori, jika tidak, file histori dituliskan secara berlebihan.


10

Anda dapat mengedit BASH prompt Anda untuk menjalankan "history -a" dan "history -r" yang disarankan Muerr:

savePS1=$PS1

(Jika Anda mengacaukan sesuatu, yang hampir dijamin)

PS1=$savePS1`history -a;history -r`

(perhatikan bahwa ini adalah tick-back; mereka akan menjalankan history -a dan history -r pada setiap prompt. Karena mereka tidak menampilkan teks apa pun, prompt Anda tidak akan berubah.

Setelah Anda mengatur variabel PS1 seperti yang Anda inginkan, atur secara permanen di file ~ / .bashrc Anda.

Jika Anda ingin kembali ke permintaan awal saat pengujian, lakukan:

PS1=$savePS1

Saya telah melakukan pengujian dasar pada ini untuk memastikan bahwa itu berfungsi, tetapi tidak dapat berbicara dengan efek samping dari menjalankan history -a;history -rpada setiap prompt.


2
Solusi kch bekerja lebih baik daripada solusi saya. Saya sekarang menggunakan solusinya di .bashrc saya.

9

Jika Anda memerlukan solusi sinkronisasi sinkronisasi bash atau zsh yang juga menyelesaikan masalah di bawah ini, maka lihat di http://ptspts.blogspot.com/2011/03/how-to-automatically-synchronize-shell.html

Masalahnya adalah sebagai berikut: Saya memiliki dua jendela shell A dan B. Di jendela shell A, saya berlari sleep 9999, dan (tanpa menunggu waktu tidur selesai) di jendela shell B, saya ingin dapat melihat sleep 9999di bash history.

Alasan mengapa sebagian besar solusi lain di sini tidak akan menyelesaikan masalah ini adalah karena mereka menulis perubahan histori mereka ke file histori menggunakan PROMPT_COMMANDatau PS1, keduanya mengeksekusi terlalu terlambat, hanya setelah sleep 9999perintah selesai.


1
Ini adalah solusi yang bagus, tetapi saya punya beberapa pertanyaan. 1. Dapatkah saya menggunakan file .bash_history asli, saya tidak ingin ada file bash history di $ HOME 2. Mungkin Anda sebaiknya mempertimbangkan untuk mengatur repo github untuk ini.
weynhamz

Tampaknya kait debug bertentangan dengan bashdb, hasil ikuti setiap kali saya memulai sesi bash. `` `bash debugger, bashdb, rilis 4.2-0.8 Hak Cipta 2002, 2003, 2004, 2006, 2007, 2008, 2009, 2010, Rocky Bernstein Ini adalah perangkat lunak gratis, dilindungi oleh Lisensi Publik Umum GNU, dan Anda dipersilakan untuk ubah dan / atau bagikan salinannya dalam kondisi tertentu. ** Kesalahan debug internal _Dbg_is_file (): argumen file null bash: _Dbg_filenames [$ fullname]: subscript array buruk `` `
weynhamz

@ Techlive Zheng: 1. .bash_history yang asli sengaja tidak didukung, karena .merged_bash_history menggunakan format file yang berbeda, jadi jika .merged_bash_history gagal dimuat dengan benar, bash tidak akan secara tidak sengaja menabrak akumulasi sejarah. Kuatnya desain, akan tetap seperti apa adanya. 2. Repo github adalah ide yang bagus secara umum, tetapi saya tidak punya waktu untuk mempertahankannya untuk proyek ini, jadi saya tidak melakukannya. - Ya, itu bertentangan dengan bashdb, dan tidak ada solusi mudah (mereka menggunakan kait yang sama). Saya tidak berencana untuk memperbaiki, tetapi saya menerima patch.
Poin

Oke terima kasih. Saya telah datang dengan ramuan yang jauh lebih sederhana dan lebih baik.
weynhamz

@ TechliveZheng: Apakah Anda akan berbagi solusi sederhana dan lebih baik dengan kami, sehingga kita semua dapat belajar darinya? (Jika demikian, harap tambahkan jawaban untuk pertanyaan itu.)
Poin

8

Anda dapat menggunakan history -auntuk menambahkan histori sesi saat ini ke histfile, kemudian gunakan history -rdi terminal lain untuk membaca histfile. 


8

Benar, Jadi akhirnya ini mengganggu saya untuk menemukan solusi yang layak:

# Write history after each command
_bash_history_append() {
    builtin history -a
}
PROMPT_COMMAND="_bash_history_append; $PROMPT_COMMAND"

Apa yang dilakukan adalah semacam penggabungan dari apa yang dikatakan di utas ini, kecuali bahwa saya tidak mengerti mengapa Anda memuat ulang sejarah global setelah setiap perintah. Saya sangat jarang peduli dengan apa yang terjadi di terminal lain, tetapi saya selalu menjalankan serangkaian perintah, misalnya di satu terminal:

make
ls -lh target/*.foo
scp target/artifact.foo vm:~/

(Contoh sederhana)

Dan di tempat lain:

pv ~/test.data | nc vm:5000 >> output
less output
mv output output.backup1

Tidak mungkin saya ingin perintah itu dibagikan


1
Alasan Anda memuat ulang riwayat setelah setiap perintah adalah karena itu perilaku yang diperlukan oleh pertanyaan (dan jadi ini sebenarnya tidak menjawab pertanyaan seperti yang diajukan).
Michael Homer

2
@MichaelHomer Fair point. Merasa bebas untuk melakukan downvote sehingga jawabannya tetap di bagian bawah, namun, saya akan menuliskannya sampai OP tidak menyadari betapa buruknya perilaku yang diminta, dan fakta bahwa ini adalah pertanyaan yang sangat googlable.
Yarek T

3
Op di sini, ya, itu kompromi yang adil. Keluhan utama saya adalah bahwa saya kehilangan sejarah. Ini harus menghentikan itu, bahkan jika itu tidak berarti pembaruan instan di seluruh sesi simultan.
Oli

7

Inilah alternatif yang saya gunakan. Ini rumit tapi itu mengatasi masalah yang @axel_c sebutkan di mana kadang-kadang Anda mungkin ingin memiliki instance history terpisah di setiap terminal (satu untuk make, satu untuk pemantauan, satu untuk vim, dll).

Saya menyimpan file riwayat tambahan terpisah yang terus saya perbarui. Saya memetakan yang berikut ini ke hotkey:

history | grep -v history >> ~/master_history.txt

Ini menambahkan semua riwayat dari terminal saat ini ke file yang disebut master_history.txt di direktori home Anda.

Saya juga memiliki hotkey terpisah untuk mencari melalui file master history:

cat /home/toby/master_history.txt | grep -i

Saya menggunakan kucing | grep karena ia meninggalkan kursor di akhir untuk memasukkan regex saya. Cara yang kurang jelek untuk melakukan ini adalah dengan menambahkan beberapa skrip ke jalur Anda untuk menyelesaikan tugas-tugas ini, tetapi hotkey berfungsi untuk tujuan saya. Saya juga secara berkala akan menarik riwayat dari host lain yang telah saya kerjakan dan menambahkan riwayat itu ke file master_history.txt saya.

Selalu menyenangkan untuk dapat dengan cepat mencari dan menemukan regex rumit yang Anda gunakan atau perl satu-liner yang Anda buat 7 bulan lalu.


6

Saya dapat menawarkan perbaikan untuk yang terakhir: pastikan variabel env HISTCONTROL tidak menentukan "ignorespace" (atau "ignoreboth").

Tapi saya merasakan sakit Anda dengan beberapa sesi bersamaan. Ini tidak ditangani dengan baik di bash.


6

Inilah peningkatan saya untuk jawaban @ lesmana . Perbedaan utama adalah bahwa windows bersamaan tidak membagikan sejarah. Ini berarti Anda dapat tetap bekerja di windows Anda, tanpa konteks dari jendela lain yang dimuat ke windows Anda saat ini.

Jika Anda secara eksplisit mengetik 'histori', ATAU jika Anda membuka jendela baru maka Anda mendapatkan histori dari semua jendela sebelumnya.

Juga, saya menggunakan strategi ini untuk mengarsipkan setiap perintah yang pernah diketik di mesin saya.

# Consistent and forever bash history
HISTSIZE=100000
HISTFILESIZE=$HISTSIZE
HISTCONTROL=ignorespace:ignoredups

_bash_history_sync() {
  builtin history -a         #1
  HISTFILESIZE=$HISTSIZE     #2
}

_bash_history_sync_and_reload() {
  builtin history -a         #1
  HISTFILESIZE=$HISTSIZE     #2
  builtin history -c         #3
  builtin history -r         #4
}

history() {                  #5
  _bash_history_sync_and_reload
  builtin history "$@"
}

export HISTTIMEFORMAT="%y/%m/%d %H:%M:%S   "
PROMPT_COMMAND='history 1 >> ${HOME}/.bash_eternal_history'
PROMPT_COMMAND=_bash_history_sync;$PROMPT_COMMAND

5

Saya memilih untuk memasukkan histori dalam file-per-tty, karena banyak orang dapat bekerja di server yang sama - memisahkan setiap perintah sesi membuatnya lebih mudah untuk diaudit.

# Convert /dev/nnn/X or /dev/nnnX to "nnnX"
HISTSUFFIX=`tty | sed 's/\///g;s/^dev//g'`
# History file is now .bash_history_pts0
HISTFILE=".bash_history_$HISTSUFFIX"
HISTTIMEFORMAT="%y-%m-%d %H:%M:%S "
HISTCONTROL=ignoredups:ignorespace
shopt -s histappend
HISTSIZE=1000
HISTFILESIZE=5000

Sejarah sekarang terlihat seperti:

user@host:~# test 123
user@host:~# test 5451
user@host:~# history
1  15-08-11 10:09:58 test 123
2  15-08-11 10:10:00 test 5451
3  15-08-11 10:10:02 history

Dengan file yang terlihat seperti:

user@host:~# ls -la .bash*
-rw------- 1 root root  4275 Aug 11 09:42 .bash_history_pts0
-rw------- 1 root root    75 Aug 11 09:49 .bash_history_pts1
-rw-r--r-- 1 root root  3120 Aug 11 10:09 .bashrc

3

Di sini saya akan menunjukkan satu masalah dengan

export PROMPT_COMMAND="${PROMPT_COMMAND:+$PROMPT_COMMAND$'\n'}history -a; history -c; history -r"

dan

PROMPT_COMMAND="$PROMPT_COMMAND;history -a; history -n"

Jika Anda menjalankan source ~ / .bashrc, $ PROMPT_COMMAND akan menjadi seperti

"history -a; history -c; history -r history -a; history -c; history -r"

dan

"history -a; history -n history -a; history -n"

Pengulangan ini terjadi setiap kali Anda menjalankan 'source ~ / .bashrc'. Anda dapat memeriksa PROMPT_COMMAND setelah setiap kali Anda menjalankan 'source ~ / .bashrc' dengan menjalankan 'echo $ PROMPT_COMMAND'.

Anda bisa melihat beberapa perintah tampaknya rusak: "history -n history -a". Tapi kabar baiknya adalah masih berfungsi, karena bagian lain masih membentuk urutan perintah yang valid (Hanya melibatkan beberapa biaya tambahan karena menjalankan beberapa perintah berulang-ulang. Dan tidak begitu bersih.)

Secara pribadi saya menggunakan versi sederhana berikut:

shopt -s histappend
PROMPT_COMMAND="history -a; history -c; history -r"

yang memiliki sebagian besar fungsi sementara tidak ada masalah seperti yang disebutkan di atas.

Hal lain yang perlu dikemukakan adalah: sebenarnya tidak ada keajaiban . PROMPT_COMMAND hanyalah variabel lingkungan bash biasa. Perintah di dalamnya dieksekusi sebelum Anda mendapatkan bash prompt (tanda $). Misalnya, PROMPT_COMMAND Anda adalah "echo 123", dan Anda menjalankan "ls" di terminal Anda. Efeknya seperti menjalankan "ls; echo 123".

$ PROMPT_COMMAND="echo 123"

output (Sama seperti menjalankan 'PROMPT_COMMAND = "echo 123"; $ PROMPT_COMMAND'):

123

Jalankan yang berikut ini:

$ echo 3

keluaran:

3
123

"history -a" digunakan untuk menulis perintah histori dalam memori ke ~ / .bash_history

"history -c" digunakan untuk menghapus perintah history dalam memori

"history -r" digunakan untuk membaca perintah history dari ~ / .bash_history ke memori

Lihat penjelasan perintah sejarah di sini: http://ss64.com/bash/history.html

PS: Seperti yang ditunjukkan oleh pengguna lain, ekspor tidak perlu. Lihat: menggunakan ekspor di .bashrc


2

Saya telah menulis skrip untuk mengatur file riwayat per sesi atau tugas berdasarkan dari berikut ini.

        # write existing history to the old file
        history -a

        # set new historyfile
        export HISTFILE="$1"
        export HISET=$1

        # touch the new file to make sure it exists
        touch $HISTFILE
        # load new history file
        history -r $HISTFILE

Tidak perlu menyimpan setiap perintah sejarah tetapi menyimpan yang saya sayangi dan lebih mudah untuk mengambilnya kemudian melalui setiap perintah. Versi saya juga mencantumkan semua file riwayat dan menyediakan kemampuan untuk mencari semuanya.

Sumber lengkap: https://github.com/simotek/scripts-config/blob/master/hiset.sh


2

Inilah solusi yang tidak mencampuradukkan sejarah dari sesi individual!

Pada dasarnya kita harus menyimpan sejarah setiap sesi secara terpisah dan membuatnya kembali pada setiap prompt. Ya, ia menggunakan lebih banyak sumber daya, tetapi tidak selambat kedengarannya - penundaan mulai terlihat hanya jika Anda memiliki lebih dari 100.000 entri riwayat.

Inilah logika intinya:

# on every prompt, save new history to dedicated file and recreate full history
# by reading all files, always keeping history from current session on top.
update_history () {
  history -a ${HISTFILE}.$$
  history -c
  history -r
  for f in `ls ${HISTFILE}.[0-9]* | grep -v "${HISTFILE}.$$\$"`; do
    history -r $f
  done
  history -r "${HISTFILE}.$$"
}
export PROMPT_COMMAND='update_history'

# merge session history into main history file on bash exit
merge_session_history () {
  cat ${HISTFILE}.$$ >> $HISTFILE
  rm ${HISTFILE}.$$
}
trap merge_session_history EXIT

Lihat inti ini untuk solusi lengkap, termasuk beberapa pengamanan dan optimalisasi kinerja.


1

Ini berfungsi untuk ZSH

##############################################################################
# History Configuration for ZSH
##############################################################################
HISTSIZE=10000               #How many lines of history to keep in memory
HISTFILE=~/.zsh_history     #Where to save history to disk
SAVEHIST=10000               #Number of history entries to save to disk
#HISTDUP=erase               #Erase duplicates in the history file
setopt    appendhistory     #Append history to the history file (no overwriting)
setopt    sharehistory      #Share history across terminals
setopt    incappendhistory  #Immediately append to the history file, not just when a term is killed

sayangnya pertanyaannya hanya untuk bash :-)
Jaleks

1
ini adalah hasil pertama di google ketika saya mencari zsh juga ... Saya kira itu mungkin membantu
Mulki

3
Anda harus mengajukan pertanyaan baru, ~ "Pertahankan riwayat zsh di banyak jendela terminal", dengan anggapan belum ada. Tidak apa-apa — bahkan didorong — untuk menjawab pertanyaan Anda sendiri jika itu pertanyaan yang bagus.
Oli

1

Saya sudah lama menginginkan ini, terutama kemampuan untuk mengambil perintah di mana dijalankan untuk mengeksekusi kembali dalam proyek baru (atau menemukan direktori dengan perintah). Jadi saya menyatukan alat ini , yang menggabungkan solusi sebelumnya untuk menyimpan sejarah CLI global dengan alat grepping interaktif yang disebut percol (dipetakan ke C ^ R). Masih licin pada mesin pertama yang saya mulai menggunakannya, sekarang dengan riwayat CLI> 2 tahun.

Itu tidak mengacaukan sejarah CLI lokal sejauh menyangkut tombol panah, tetapi memungkinkan Anda mengakses sejarah global dengan cukup mudah (yang Anda juga dapat memetakan ke sesuatu selain C ^ R)


ini untuk zsh?
sjas

1
ya, saya membuatnya untuk zsh pada awalnya. Membuatnya bekerja untuk bash dan ikan juga. Beri tahu saya apakah itu berfungsi atau tidak. Saya belum mengubahnya dalam beberapa saat dan saya tidak yakin seberapa jelas saya dalam instruksi instal saya
Gordon Wells

1

Karena saya lebih suka riwayat tak terbatas yang disimpan dalam file khusus. Saya membuat konfigurasi ini berdasarkan https://stackoverflow.com/a/19533853/4632019 :

export HISTFILESIZE=
export HISTSIZE=
export HISTTIMEFORMAT="[%F %T] "

export HISTFILE=~/.bash_myhistory
PROMPT_COMMAND="history -a; history -r; $PROMPT_COMMAND"

-1

Berikut ini cuplikan dari .bashrc saya dan penjelasan singkat di mana pun dibutuhkan:

# The following line ensures that history logs screen commands as well
shopt -s histappend

# This line makes the history file to be rewritten and reread at each bash prompt
PROMPT_COMMAND="$PROMPT_COMMAND;history -a; history -n"
# Have lots of history
HISTSIZE=100000         # remember the last 100000 commands
HISTFILESIZE=100000     # start truncating commands after 100000 lines
HISTCONTROL=ignoreboth  # ignoreboth is shorthand for ignorespace and     ignoredups

HISTFILESIZE dan HISTSIZE adalah preferensi pribadi dan Anda dapat mengubahnya sesuai selera Anda.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.