Riwayat BASH terpotong menjadi 500 baris pada setiap login

22

Untuk beberapa alasan, saya tidak bisa mendapatkan sistem saya untuk menyimpan riwayat BASH saya setelah reboot. Berikut adalah bagian yang relevan dari saya ~/.bashrc:

shopt -s histappend
PROMPT_COMMAND='history -a; updateWindowTitle'
export HISTCONTROL=ignoredups
export HISTSIZE=9999
export HISTFILESIZE=999999
export HISTFILE="$HOME/.bash_history"

Sejauh yang saya tahu itu semua adalah opsi yang diperlukan (saya tahu saya dulu bisa menyimpan sejarah di beberapa reboot tanpa semua ini di masa lalu). Namun, meskipun telah menambahkan opsi ini beberapa reboot lalu, saya masih kehilangan sebagian besar sejarah saya setelah reboot. Ini tidak kosong, tetapi tidak memiliki garis 9999 yang saya miliki sebelum me-reboot.

Sebelum ada yang mengeluh, ya saya sudah baca pertanyaan ini. Saya telah menerapkan beberapa saran mereka sebagaimana tercantum di atas, sisanya tidak membantu atau tidak relevan:

Jika ada perintah lain yang relevan di sana, Anda dapat melihat keseluruhan saya di ~/.bashrc sini .

Jadi, apa yang saya lewatkan? Mengapa riwayat saya tidak disimpan? Jika ada yang berpikir file lain mungkin relevan beri tahu saya dan saya akan mempostingnya. Saya memeriksa dengan menjalankan grep -i hist \.*di saya $HOMEyang menunjukkan bahwa satu-satunya .file yang relevan berisi string histatau HISTitu .bashrc.

Saya menjalankan Linux Mint Debian Edition, GNU bash, versi 4.2.36 (1) -release (x86_64-pc-linux-gnu) dan terminal emulator favorit saya (dalam kasus yang relevan) adalah terminator.


MEMPERBARUI:

Mengikuti saran @ mpy di komentar, saya mengubah ~/.bashrcpengaturan saya HISTFILE=~/bash_historysebagai kebalikan dari default ~/.bash_historydan yang tampaknya memecahkan masalah untuk shell interaktif . Cangkang login masih menampilkan perilaku yang sama, dengan riwayat terpotong pada 500baris. Namun, tidak ada HISTvariabel terkait yang diatur dalam file yang relevan:

$ for f in /etc/profile ~/.profile ~/.bash_profile ~/.bash_login; do \
   echo -ne "$f :"; echo `grep HIST $f`; \
done
/etc/profile :
/home/terdon/.profile :grep: /home/terdon/.profile: No such file or directory
/home/terdon/.bash_profile :grep: /home/terdon/.bash_profile: No such file or directory
/home/terdon/.bash_login :grep: /home/terdon/.bash_login: No such file or directory
$ grep -r HIST /etc/profile.d/  <-- returns nothing

Jadi, mengapa pengaturan HISTSIZEdan HISTFILESIZEdalam ~/.bashrctidak cukup kecuali saya secara eksplisit mengatur $HISTFILEsesuatu selain default ~/.bash_history?

terdon
sumber
Apakah Anda pemilik .bash_history atau root? Do ls-l .bash_history
Adnan Bhatti
1
@ MSStp ya, itu milik saya. Terima kasih atas sarannya tetapi saya tidak melihat bagaimana itu bisa menjadi masalah izin, baik saya telah membaca / menulis aksesnya atau tidak. Karena beberapa sejarah diselamatkan, saya jelas melakukannya. Jika bash memiliki pengaturan yang menyebabkan masalah ketika file ini tidak dimiliki oleh pengguna, itu akan mengeluh atau seluruh fungsi riwayat tidak akan berfungsi.
terdon
ketika Anda menjalankan historyperintah, output yang Anda lihat identik dengan apa yang Anda lihat, jalankan cat .bash_history, selain nomor baris? Maksud saya apakah historywaktu daftar perintah perangko atau informasi lainnya? Alasan saya bertanya adalah, jika Anda melihat hal-hal esoterik ini, itu berarti, ada modul / fungsi / program lain, yang mengacaukan sejarah shell dan versi yang salah atau kereta apa pun itu, mungkin menyebabkan Anda bersedih. .
MelBurslan
@Mel_Burslan ya itu sama, satu-satunya perbedaan adalah nomor baris.
terdon
2
Ok, saran yang agak aneh, tapi ini juga masalah yang aneh ;): Coba file lain sebagai HISTFILE, bukan default ~/.bash_history. Penjelasan yang sangat dikonstruksi: Saya menganggap bash adalah shell default Anda, jadi pada sistem start shell non-interaktif adalah induk dari sesi X Anda (saya juga menganggap Anda menggunakan X), yang tidak akan tahu apa-apa tentang opsi histappend (karena .bashrc hanya dibaca oleh shell interaktif), sehingga selama shell induk ini berjalan semuanya baik-baik saja, tetapi setelah penghentian (yaitu sistem berhenti) itu akan menimpa ~/.bash_history(yang default) dan mengacaukan sejarah Anda ...
mpy

Jawaban:

17

Masalahnya sebenarnya bermuara pada perilaku berbeda dari shell masuk dan non-login. Saya telah menetapkan variabel yang mengontrol riwayat di file saya ~/.bahsrc. File ini tidak dibaca ketika seseorang memulai shell login, itu hanya dibaca oleh shell interaktif, non-login (dari man bash):

Ketika bash dipanggil sebagai shell login interaktif, atau sebagai shell non-interaktif dengan --loginopsi, bash pertama kali membaca dan mengeksekusi perintah dari file /etc/profile, jika file itu ada. Setelah membaca file itu, ia mencari ~ / .bash_profile,, ~/.bash_logindan ~/.profile, dalam urutan itu, dan membaca dan mengeksekusi perintah dari yang pertama yang ada dan dapat dibaca. The --noprofilepilihan mungkin digunakan ketika shell dimulai untuk menghambat perilaku ini.

[. . . ]

Ketika shell interaktif yang bukan shell login dimulai, bash membaca dan mengeksekusi perintah dari ~ / .bashrc, jika file itu ada. Ini dapat dihambat dengan menggunakan opsi --norc. Opsi file --rcfile akan memaksa bash untuk membaca dan menjalankan perintah dari file daripada ~ / .bashrc.

Oleh karena itu, setiap kali saya login, atau turun menjadi tty, atau menggunakan ssh, .historyfile semakin terpotong karena saya belum mengaturnya ke ukuran yang tepat ~/.profilejuga. Saya akhirnya menyadari ini dan hanya mengatur variabel di ~/.profile tempat mereka berada , bukan~/.bashrc

Jadi, alasan saya ~/.historyterpotong adalah karena saya hanya mengatur variabel SEJARAH dalam file yang dibaca oleh shell non-login yang interaktif dan oleh karena itu setiap kali saya menjalankan tipe shell yang berbeda, variabel akan diabaikan dan file akan dipotong demikian.

terdon
sumber
Poin yang sangat bagus, terima kasih sudah berbagi! Namun, saya tidak setuju dengan: File ini tidak dibaca ketika seseorang memulai shell login, itu hanya dibaca oleh shell interaktif. Karena shell login juga bisa interaktif. Kalau tidak, seluruh mekanisme sejarah tidak masuk akal. IMHO .bashrctidak dibaca oleh (shell non-interaktif ATAU login).
mpy
@ mpy Memang, maaf, saya maksudkan shell yang interaktif dan non-login. Jawaban diedit.
terdon
1
@terdon, idiom yang umum adalah bahwa opsi shell interaktif tidak masuk ~ / .profile atau ~ / .bash_profile. Opsi shell interaktif dimasukkan ke ~ / .bashrc. Untuk menghindari keharusan mempertahankan pengaturan di dua tempat, perintah berikut dapat diletakkan di bagian atas ~ / .bash_profile: export BASH_ENV=~/.bashrc ; if [ -f ~/.bashrc ]; then . ~/.bashrc; fi... dan di bagian atas ~ / .bashrc beri tanda centang untuk memastikan Anda benar-benar berjalan secara interaktif: [ -z "$PS1" ] && return... Tentu saja, itu hanya sebuah idiom.
Noah Spurrier
1
@NoahSpurrier BASH_ENVtidak relevan, hanya memengaruhi shell yang tidak interaktif. Adapun "idiom", itu adalah sesuatu yang Debian mulai dan dengan yang saya pribadi tidak setuju. Saya sering memiliki opsi grafis ( xsetdan sejenisnya) di .bashrc saya dan saya tidak ingin yang aktif ketika saya menjalankan shell login baik dari tty atau melalui ssh. Saya ingin .profile dan .bashrc saya terpisah. Banyak (walaupun tidak semua) sumber masuk manajer. Profil ketika Anda masuk sehingga variabel global paling baik diatur di sana di mana mereka hanya akan dibaca sekali dan tidak setiap kali Anda membuka terminal.
terdon
1
@ WillsonF ya. File dibaca berurutan dan file pribadi ( ~/.profileatau ~/.bashrc) dibaca terakhir. Apa pun yang diatur dalam mereka akan diutamakan daripada pengaturan global. Anda benar, Anda seharusnya tidak mengatur variabel-variabel tersebut di /etc/bash.bashrc. Gunakan ~/.profile(atau ~/.bash_profile) sebagai gantinya.
terdon
11

Saran saya adalah menggunakan file lain sebagai HISTFILE, bukan default ~/.bash_history.

Meskipun saya tidak memiliki penjelasan analitis, saya akan mencoba untuk menguraikan apa yang menuntun saya ke saran ini: Jika Anda menggunakan bashshell (login) default Anda dan juga menggunakan X(yang keduanya sangat mungkin), Anda memiliki bashinstance yang berjalan tepat setelah (grafis) ) Gabung:

systemd
 ...
  |-login
  |   `-bash      <<====
  |       `-slim
  |           |-X -nolisten tcp vt07 -auth /var/run/slim.auth
  |           |  `-{X}
  |           `-fluxbox
  |               `-xterm -bg black -fg white
  |                   `-bash
 ...

Saya pikir contoh ini adalah shell login, jadi itu tidak membaca Anda ~/.bashrcdan karenanya tidak akan tahu apa-apa tentang histappendopsi:

man bash (1) : Ketika shell interaktif yang bukan shell login dimulai, bash membaca dan mengeksekusi perintah dari /etc/bash.bashrc dan ~ / .bashrc, jika file-file ini ada. (...)

Selama "shell orangtua" ini berjalan, semuanya baik-baik saja, tetapi setelah dihentikan (yaitu sistem berhenti) itu akan menimpa ~/.bash_history(karena itu nilai default) dan mengacaukan riwayat Anda atau klip itu pada sistem mulai (lagi default) 500 garis. (Atau mungkin keduanya ...)

Ini mengejutkan saya juga, bahwa tidak cukup untuk memasukkan konfigurasi sejarah ~/.bashrc, karena ini seharusnya tidak menjadi pengaturan yang tidak biasa. Saya tidak punya penjelasan untuk itu.


Mengenai masalah Anda, bahwa "Shell login masih menampilkan perilaku yang sama", Anda dapat mencoba untuk memasukkan konfigurasi sejarah juga di ~/.bash_profile:

man bash (1) : Ketika bash dipanggil sebagai shell login interaktif, atau sebagai shell non-interaktif dengan opsi --login, ia pertama kali membaca dan mengeksekusi perintah dari file / etc / profile, jika file itu ada. Setelah membaca file itu, ia mencari ~ / .bash_profile, (...)

Sayangnya saya tidak dapat memposting penjelasan yang lebih tepat dengan detail dari bashkonfigurasi saya sendiri , karena saya seorang zshpria ...

mpy
sumber
2
Secara eksplisit mengatur opsi histori di saya ~/.bash_profilememecahkan masalah. Saya sekarang menggunakan ~/.bash_historysebagai file riwayat saya tetapi hanya menambahkan semua baris dari yang ~/.bashrcditunjukkan dalam pertanyaan saya ke ~/.bash_profile. Masih tidak yakin siapa yang mengacaukan kerang interaktif, tetapi tampaknya berfungsi sekarang, terima kasih!
terdon
1
Maaf tidak menerima tetapi saya lupa mengirim jawaban yang menjelaskan apa yang sedang terjadi. Saya menemukan jawabannya dengan bantuan dari @Gilles beberapa waktu yang lalu dan akhirnya mendapatkan jawaban. Saya ingin menerima milik saya karena itu sebenarnya menjelaskan masalah alih-alih menawarkan solusi (sangat baik) dan dapat membantu pengunjung masa depan.
terdon
2

Karena semua pengaturan Anda sesuai dengan halaman manual, dan karena file histori tidak dibatasi oleh ukuran (byte), satu-satunya penjelasan yang mungkin bisa saya pikirkan. Itu ada hubungannya dengan bagaimana cangkangnya mati.

Menurut referensi online, jalan keluar yang anggun (histori disimpan) hanya terjadi ketika shell menerima SIGHUP. Saya tidak bisa menjelaskan bagaimana sistem Anda menyebarkan sinyal ketika dinyalakan kembali, tetapi saya menduga bahwa shell Anda berhenti dengan SIGKILL atau SIGPWR.

Mungkin karena WM Anda berjalan secara tidak sinkron (tunggu) dan emulator terminal muncul dari WM di mana bash mendapatkan sinyal pemaksaan keluar selain SIGHUP. Bisa juga bahwa OS adalah untuk dengan cepat mengirim "final kill" ke semua proses sebelum SIGHUP yang anggun berhasil mencapai shell melalui X -> WM -> xterm, mungkin karena X atau WM membutuhkan waktu lebih lama untuk keluar daripada dibutuhkan agar OS siap turun.

Saya berada di perairan yang dalam dengan hal-hal ini, tetapi saya pikir sesuatu di sepanjang garis itu menyebabkan perilaku yang tidak menentu. Saya pernah mengalami masalah ini sebelumnya, dan obat yang paling kuat ada exitdi bash di mana Anda ingin menyimpan sejarah.

Saya perhatikan history -adalam pertanyaan Anda, dan saya tidak bisa memikirkan mengapa itu tidak cukup untuk melestarikan sejarah.

Anda bisa memecahkan masalah dengan mencari tahu apa yang benar-benar membunuh bash Anda dan beralih ke mencari tahu di mana sinyal berasal dan memperbaiki masalah di sana, atau hanya menyiram sejarah ketika Anda tahu sinyal mana yang terakhir (dengan asumsi disk masih online saat itu ):

trap "echo got 1  >/tmp/sig1;  exit" SIGHUP
trap "echo got 2  >/tmp/sig2;  exit" SIGINT
trap "echo got 15 >/tmp/sig15; exit" SIGTERM
 .. and so on...

Tangkapan layar yang disertakan menggambarkan apa yang saya bicarakan di paragraf kedua dan ketiga. Urutan ada saya shell dari kiri , bunuh shell kiri dari kanan dan cat sejarah.

bash bash

Saat memulai, (...) File yang dinamai dengan nilai HISTFILE dipotong, jika perlu, tidak lebih dari jumlah baris yang ditentukan oleh nilai HISTFILESIZE (+ default 500).

Jika opsi histappend shell diaktifkan (+ default di sini), baris ditambahkan ke file histori, jika tidak file histori akan ditimpa.

referensi online

3.7.6 Sinyal

Ketika Bash bersifat interaktif, dengan tidak adanya jebakan, ia mengabaikan SIGTERM (sehingga 'kill 0' tidak membunuh shell interaktif), dan SIGINT ditangkap dan ditangani (sehingga menunggu buildin dapat terputus). Ketika Bash menerima SIGINT, ia keluar dari setiap loop eksekusi. Dalam semua kasus, Bash mengabaikan SIGQUIT. Jika kontrol pekerjaan berlaku (lihat Kontrol Pekerjaan), Bash mengabaikan SIGTTIN, SIGTTOU, dan SIGTSTP.

Perintah non-builtin yang dimulai oleh Bash memiliki penangan sinyal diatur ke nilai-nilai yang diwarisi oleh shell dari induknya. Ketika kontrol pekerjaan tidak berlaku, perintah asinkron mengabaikan SIGINT dan SIGQUIT sebagai tambahan dari penangan bawaan ini. Perintah dijalankan sebagai akibat dari penggantian perintah mengabaikan sinyal kontrol pekerjaan yang dihasilkan keyboard SIGTTIN, SIGTTOU, dan SIGTSTP.

Shell keluar secara default setelah menerima SIGHUP. Sebelum keluar, shell interaktif mengirim ulang SIGHUP ke semua pekerjaan, berjalan atau berhenti. Pekerjaan yang dihentikan dikirim SIGCONT untuk memastikan bahwa mereka menerima SIGHUP. Untuk mencegah shell mengirim sinyal SIGHUP ke pekerjaan tertentu, itu harus dihapus dari tabel pekerjaan dengan builtin disown (lihat Pekerjaan Control Builtins) atau ditandai untuk tidak menerima SIGHUP menggunakan disown -h.

Jika opsi shell huponexit telah diatur dengan shopt (lihat Shopt Builtin), Bash mengirimkan SIGHUP ke semua pekerjaan ketika shell login interaktif keluar.

Jika Bash sedang menunggu perintah untuk menyelesaikan dan menerima sinyal yang telah ditetapkan jebakan, jebakan tidak akan dieksekusi sampai perintah selesai. Ketika Bash sedang menunggu perintah asinkron melalui wait builtin, penerimaan sinyal di mana trap telah diatur akan menyebabkan wait builtin kembali segera dengan status keluar lebih besar dari 128, segera setelah itu trap dieksekusi.

tangkapan layar demonstratif

sinyal

Ярослав Рахматуллин
sumber
Saya tidak benar-benar mendapatkan apa yang Anda lakukan di tangkapan layar itu. Apa /tmp/psoyang kau bunuh? Saya mengerti maksud Anda tentang berbagai sinyal membunuh (meskipun seperti yang Anda katakan, saya pikir itulah yang history -aharus dihadapi). Saya akan mengujinya sebentar dan melaporkannya kembali.
terdon
$ cat tmp / ps * \ n ps -o pid = | head -n1> ~ / tmp / pso \ n 17201 \ n
Ярослав Рахматуллин
0

Periksa / etc / profile dan /etc/profile.d/*

Mungkin ada sesuatu yang mengacaukan pengaturan sejarah di sana.

mabagu
sumber
Terima kasih, tetapi grep -r HIST /etc/profile.d/tidak mengembalikan apa pun, dan saya sudah memeriksanya /etc/profile.
terdon