Perbarui riwayat bash di terminal lain saat keluar dari satu terminal

15

Saya tahu pertanyaan ini tidak jelas, seperti yang ditanyakan di sini terus diperbarui (dan digandakan di sini).

Apa yang saya coba capai sedikit berbeda. Saya tidak suka gagasan prompt saya menulis ulang file setiap lssaya ketik ( history -a; history -c; history -r).

Saya ingin memperbarui file saat keluar. Itu mudah (sebenarnya, default), tetapi Anda harus menambahkan alih-alih menulis ulang:

shopt -s histappend

Sekarang, ketika terminal ditutup, saya ingin membuat semua yang lain tetap terbuka untuk mengetahui pembaruan.

Saya lebih suka melakukan ini tanpa memeriksa $PS1pada setiap commandyang saya ketik. Saya pikir akan lebih baik untuk menangkap semacam sinyal. Bagaimana Anda akan melakukannya? Jika tidak memungkinkan, mungkin sederhana cronjob?

Bagaimana kita bisa memecahkan teka-teki ini?

Dr Beco
sumber
1
Perhatikan bahwa zsh melakukan hal ini di luar kotak (dan memiliki banyak opsi untuk menyempurnakan berbagi riwayat).
Gilles 'SANGAT berhenti menjadi jahat'
Terima kasih @Gilles; Lucu, bertahun-tahun menggunakan Linux dan saya tidak pernah mencoba apa pun kecuali bash. Mungkin sudah waktunya untuk memeriksa sesuatu yang baru, hanya untuk bersenang-senang.
Dr Beco

Jawaban:

15

Sinyal kreatif dan melibatkan, katamu? BAIK:

trap on_exit EXIT
trap on_usr1 USR1

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

on_usr1() {
    history -n
}

Chuck itu masuk .bashrcdan pergi. Ini menggunakan sinyal untuk memberi tahu setiap bashproses untuk memeriksa entri sejarah baru ketika yang lain keluar. Ini sangat mengerikan, tetapi benar-benar berfungsi.


Bagaimana cara kerjanya?

trapmenetapkan pengendali sinyal untuk sinyal sistem atau salah satu peristiwa internal Bash. The EXITevent adalah setiap penghentian dikendalikan dari shell, sementara USR1ini SIGUSR1, sinyal berarti kita mengambil alih.

Setiap kali shell keluar, kami:

  • Tambahkan semua riwayat ke file secara eksplisit.
  • Nonaktifkan SIGUSR1pawang dan buat cangkang ini mengabaikan sinyal.
  • Kirim sinyal ke semua bashproses yang berjalan dari pengguna yang sama.

Ketika sebuah SIGUSR1tiba, kami:

  • Muat semua entri baru dari file riwayat ke dalam daftar riwayat di dalam memori shell.

Karena cara Bash menangani sinyal, Anda tidak akan benar-benar mendapatkan data sejarah baru sampai Anda menekan Enterwaktu berikutnya, jadi ini tidak melakukan lebih baik di bagian depan itu daripada menempatkan history -nke dalam PROMPT_COMMAND. Itu menyimpan membaca file terus-menerus ketika tidak ada yang terjadi, dan tidak ada tulisan sama sekali sampai shell keluar.


Namun, masih ada beberapa masalah di sini. Yang pertama adalah respons default SIGUSR1adalah untuk menghentikan shell. Setiap bashproses lain (menjalankan skrip shell, misalnya) akan dimatikan. .bashrctidak dimuat oleh cangkang non-interaktif. Sebagai gantinya, sebuah file bernama by BASH_ENVdimuat : Anda dapat mengatur variabel itu di lingkungan Anda secara global untuk mengarah ke file dengan:

trap '' USR1

di dalamnya untuk mengabaikan sinyal di dalamnya (yang menyelesaikan masalah).

Akhirnya, meskipun ini melakukan apa yang Anda minta, pemesanan yang Anda dapatkan akan sedikit tidak biasa. Secara khusus, bit histori akan diulang dalam urutan yang berbeda saat mereka dimuat dan disimpan secara terpisah. Itu pada dasarnya melekat pada apa yang Anda minta, tetapi perlu diketahui bahwa up-arrow history menjadi jauh lebih tidak berguna pada saat ini. Pergantian sejarah dan sejenisnya akan dibagikan dan berfungsi dengan baik.

Michael Homer
sumber
Saya ingin tahu apakah Anda mengaktifkan cap waktu di dalam .bashrcfile, dan kemudian ada sesuatu seperti cronjob datang dan menggunakan file secara berkala, mengirim SIGUSR1sesuai potongan Anda, apakah Anda bisa mendapatkan kembali sejarah panah naik kronologis?
forquare
Ini adalah solusi yang rapi, tetapi sebenarnya proses lain berakhir pada USR1. Apakah perilaku ini juga terjadi pada USR2?
Dr Beco
Saya akan menambahkan komentar kedua, karena saya heran. Bagaimana proses mengaitkan JANGKA dengan USR1? Bukankah USR1 sesuatu untuk digunakan hanya oleh pengguna ?? Apakah ini beberapa linux bug?? Mengapa proses lain menangkap USR1? (Saya tahu ini tidak dimaksudkan untuk dibahas di sini, tapi mungkin saya akan menjelaskannya di tempat yang benar)
Dr Beco
Perilaku default hampir semua sinyal adalah untuk mengakhiri; itu ditentukan dalam POSIX . Itu bukan bug. Bash akan membiarkan Anda menentukan bahwa sinyal akan diabaikan untuk semua prosesnya, jadi itu tidak masalah untuk tujuan kami.
Michael Homer
Terima kasih @MichaelHomer. Apakah spesifikasi yang Anda maksudkan dilakukan BASH_ENVseperti yang dinyatakan dalam jawaban ini? Atau apakah Anda tahu cara yang lebih standar untuk mematikan kejahatan ini?
Dr Beco