Cập nhật lịch sử bash trên các thiết bị đầu cuối khác khi thoát khỏi một thiết bị đầu cuối


14

Tôi biết câu hỏi này không tối nghĩa, vì nó được hỏi ở đây tiếp tục cập nhật (và trùng lặp ở đây).

Những gì tôi đang cố gắng để đạt được là một chút khác nhau. Tôi không thích ý tưởng nhắc nhở tôi viết lại một tập tin mỗi khi lstôi gõ ( history -a; history -c; history -r).

Tôi muốn cập nhật các tập tin khi thoát. Điều đó thật dễ dàng (thực ra là mặc định), nhưng bạn cần phải chắp thêm thay vì viết lại:

shopt -s histappend

Bây giờ, khi một thiết bị đầu cuối được đóng lại, tôi muốn làm cho tất cả các thiết bị khác vẫn mở để nhận biết về bản cập nhật.

Tôi thích làm điều này mà không cần kiểm tra $PS1trên mỗi commandmà tôi gõ. Tôi nghĩ sẽ tốt hơn nếu bắt được một số tín hiệu. Bạn làm điều đó như thế nào? Nếu không thể, có thể đơn giản cronjob?

Làm thế nào chúng ta có thể giải câu đố này?


1
Lưu ý rằng zsh thực hiện việc này ngay lập tức (và có nhiều tùy chọn để tinh chỉnh chia sẻ lịch sử).
Gilles 'SO- đừng trở nên xấu xa'

Cảm ơn @Gilles; Thật buồn cười, nhiều năm sử dụng Linux và tôi chưa bao giờ thử bất cứ điều gì ngoài bash. Có lẽ đã đến lúc kiểm tra một cái gì đó mới, chỉ để cho vui.
Bác sĩ Beco

Câu trả lời:


14

Sáng tạo và liên quan đến tín hiệu, bạn nói gì? ĐỒNG Ý:

trap on_exit EXIT
trap on_usr1 USR1

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

on_usr1() {
    history -n
}

Chuck mà vào .bashrcvà đi. Điều này sử dụng các tín hiệu để báo cho mọi bashquá trình kiểm tra các mục lịch sử mới khi một mục khác thoát ra. Điều này là khá khủng khiếp, nhưng nó thực sự hoạt động.


Làm thế nào nó hoạt động?

trapđặt một bộ xử lý tín hiệu cho tín hiệu hệ thống hoặc một trong các sự kiện bên trong của Bash. Các EXITsự kiện là bất kỳ chấm dứt kiểm soát của vỏ, trong khi USR1SIGUSR1một tín hiệu vô nghĩa chúng ta đang chiếm giữ.

Bất cứ khi nào vỏ thoát ra, chúng tôi:

  • Nối tất cả lịch sử vào tập tin một cách rõ ràng.
  • Vô hiệu hóa SIGUSR1trình xử lý và làm cho lớp vỏ này bỏ qua tín hiệu.
  • Gửi tín hiệu cho tất cả các bashquy trình đang chạy từ cùng một người dùng.

Khi SIGUSR1đến nơi, chúng tôi:

  • Tải tất cả các mục mới từ tệp lịch sử vào danh sách lịch sử trong bộ nhớ của shell.

Do cách Bash xử lý tín hiệu, bạn sẽ không thực sự có được dữ liệu lịch sử mới cho đến khi bạn nhấn Entervào lần tiếp theo, vì vậy điều này không làm gì tốt hơn ở mặt trước đó hơn là đưa history -nvào PROMPT_COMMAND. Tuy nhiên, nó không lưu đọc tệp khi không có gì xảy ra, và không có chữ viết nào cho đến khi thoát khỏi vỏ.


Vẫn còn một vài vấn đề ở đây. Đầu tiên là phản hồi mặc định SIGUSR1là chấm dứt shell. Bất kỳ bashquy trình nào khác (chạy tập lệnh shell chẳng hạn) sẽ bị hủy. .bashrckhông được tải bởi các vỏ không tương tác. Thay vào đó, một tệp có tên BASH_ENVđược tải : bạn có thể đặt biến đó trong môi trường của mình trên toàn cầu để trỏ đến một tệp có:

trap '' USR1

trong đó để bỏ qua các tín hiệu trong chúng (giải quyết vấn đề).

Cuối cùng, mặc dù điều này làm những gì bạn yêu cầu, thứ tự bạn nhận được sẽ hơi bất thường. Cụ thể, các bit của lịch sử sẽ được lặp lại theo các thứ tự khác nhau khi chúng được tải lên và lưu riêng. Điều đó về cơ bản vốn có trong những gì bạn yêu cầu, nhưng hãy lưu ý rằng lịch sử mũi tên lên sẽ trở nên ít hữu ích hơn vào thời điểm này. Lịch sử thay thế và tương tự sẽ được chia sẻ và làm việc tốt, mặc dù.


Tôi tự hỏi nếu bạn kích hoạt thời gian dập trong .bashrctệp, và sau đó có một cái gì đó giống như một cronjob xuất hiện và sử dụng tệp theo định kỳ, gửi một SIGUSR1đoạn mã theo bạn, liệu bạn có thể lấy lại lịch sử mũi tên theo thời gian không?
forapes

Đó là một giải pháp gọn gàng, nhưng thực tế các quy trình khác chấm dứt trên USR1. Liệu hành vi này cũng xảy ra với USR2?
Bác sĩ Beco

Tôi sẽ thêm một bình luận thứ hai, bởi vì tôi ngạc nhiên. Làm thế nào đến quá trình liên kết TATE với USR1? Không phải USR1 một cái gì đó chỉ được sử dụng bởi người dùng ?? Đây có phải là một số linux bug?? Tại sao quá trình khác đang bắt USR1? (Tôi biết nó không có nghĩa là được thảo luận ở đây, nhưng có lẽ tôi sẽ đưa nó ra ánh sáng ở đúng nơi)
Tiến sĩ Beco

Hành vi mặc định của hầu hết tất cả các tín hiệu là chấm dứt; nó được chỉ định trong POSIX . Đó không phải là một lỗi. Bash sẽ cho phép bạn xác định rằng tín hiệu sẽ bị bỏ qua cho tất cả các quy trình của nó, tuy nhiên, vì vậy điều đó tốt cho mục đích của chúng tôi.
Michael Homer

Cảm ơn @MichaelHome. Đây có phải là đặc điểm kỹ thuật mà bạn muốn thực hiện BASH_ENVnhư đã nêu trong câu trả lời này? Hay bạn có biết một cách tiêu chuẩn hơn để tắt cái ác này?
Bác sĩ Beco
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.