Lệnh lịch sử bên trong tập lệnh bash


20

Lịch sử là một lệnh được xây dựng bằng vỏ mà tôi không thể sử dụng nó trong tập lệnh BASH. Vì vậy, có cách nào đạt được điều này bằng cách sử dụng tập lệnh BASH không?
Ở đây chúng tôi đi kịch bản của tôi cho bạn:

#!/bin/bash
history |  tail -100 > /tmp/history.log
cd /tmp
uuencode history.log history.txt  | mail -s "History log of server" hello@hel.com

Câu trả lời:


31

Bash vô hiệu hóa lịch sử trong các shell không tương tác theo mặc định, nhưng bạn có thể bật nó lên.

#!/bin/bash
HISTFILE=~/.bash_history
set -o history
history | tail 

Nhưng nếu bạn đang cố gắng theo dõi hoạt động trên máy chủ đó, lịch sử shell là vô ích (việc chạy các lệnh không hiển thị trong lịch sử) là chuyện nhỏ. Xem Làm thế nào tôi có thể đăng nhập tất cả các quá trình khởi chạy trong Linux .

Nếu bạn đang gỡ lỗi một tập lệnh thì lịch sử shell không phải là cách tốt nhất để có được thông tin hữu ích. Một công cụ tốt hơn nhiều là công cụ theo dõi gỡ lỗi: đặt set -xgần đầu tập lệnh. Các dấu vết được viết cho lỗi tiêu chuẩn.


Điều này từ chối làm việc trong một kịch bản:histtest.sh: 5: set: Illegal option -o history
Ken Sharp

4
@KenSharp Đó là vì bạn đã cố gắng sử dụng nó trong tập lệnh sh (và bạn shđang phán đoán nhanh bằng cách diễn đạt chính xác của thông báo lỗi). Để truy cập lịch sử của bash, bạn cần sử dụng bash (tập lệnh bắt đầu bằng #!/bin/bashhoặc #!/usr/bin/env bash).
Gilles 'SO- ngừng trở nên xấu xa'

1
@KenSharp Đúng vậy. Bạn rõ ràng đã chạy nó dưới dấu gạch ngang, đưa ra thông báo lỗi. Bash không có thông báo lỗi Illegal option(nó sẽ nói set: history: invalid option name).
Gilles 'SO- ngừng trở nên xấu xa'

vấn đề với điều này là nó cho biết thêm tất cả các lệnh sau set -o history để lịch sử mà sau đó sẽ được nhồi với các mục như if [... vars=$(..., vv
Nath

1
@nath Đó là những gì câu hỏi yêu cầu. Nó là khá nhiều vô nghĩa, như tôi chỉ ra. Giám sát hoạt động là một vấn đề khó khăn mà lịch sử vỏ sẽ không giải quyết được. Nếu bạn đang gỡ lỗi một tập lệnh thì set -xsẽ hữu ích hơn rất nhiều.
Gilles 'SO- ngừng trở nên xấu xa'

6

Tôi không chắc liệu nó có thực sự sử dụng khả năng lịch sử khi chạy không tương tác hay không, nếu không, mọi tập lệnh shell bạn chạy sẽ làm lộn xộn lịch sử lệnh của bạn.

Tại sao không trực tiếp vào nguồn ${HOME}/.bash_history, thay thế history | tail -100bằng tail -100 ${HOME}/.bash_history. (Nếu bạn sử dụng dấu thời gian, có lẽ bạn phải làm gì đó dọc theo dòng grep -v ^# ${HOME}/.bash_history | tail -100).


Thật vậy, với dấu thời gian, bạn thực sự nên greq -v '^#[0-9]\+$'(đôi khi tôi "thực thi" các bình luận trong vỏ của mình ...)
PlasmaBinturong

Và thực tế, trong trường hợp của tôi, tôi cần sử dụng số dòng lịch sử chính xác , nhưng có sự khác biệt giữa đầu ra historyvà đầu ra của grepphương thức ...
PlasmaBinturong

Ok, cách khắc phục là đồng bộ hóa danh sách lịch sử với tệp lịch sử như thế này : history -a; history -c; history -r. (thêm, xóa, đọc)
PlasmaBinturong

2

Nếu bạn muốn sử dụng đầu ra của historylệnh từ phiên shell hoạt động trong tập lệnh, bạn có thể sử dụng bí danh để chạy lệnh trước. Sau đó, trong cùng một bí danh, bạn có thể gọi phần còn lại của tập lệnh. Với cấu hình như vậy, bạn có thể đạt được kết quả cơ bản giống như có historylệnh trong tập lệnh thực tế.

Chẳng hạn, bạn có thể tạo một bí danh như thế này, giả sử tên của tập lệnh là script.sh:

alias hy_tmp='history | tail -100 > /tmp/history.log ; bash /patch/to/script.sh'

Và thay đổi tập lệnh này:

#!/bin/bash
cd /tmp
uuencode history.log history.txt  | mail -s "History log of server" hello@hel.com

Tôi đã tìm thấy câu hỏi này trong khi viết một quy trình để kết hợp, sắp xếp và đồng bộ hóa ~/bash_historycác tệp trên hai máy tính để dễ dàng tìm kiếm các lệnh tôi đã sử dụng trước đây.

Ít gặp rắc rối hơn khi cập nhật tệp lịch sử tích lũy của tôi mà không phải đăng nhập vào trình bao mới để ~/bash_historycập nhật. Để giám sát một máy chủ, điều này rõ ràng sẽ không hoạt động, như đã đề cập trong các câu trả lời khác.

Cách sử dụng của tôi nói riêng là:

alias hbye='history | cut -c 8- > /home/chris/.bash_history_c; bash /hby.sh

Tập lệnh hby.shsau đó kéo tất cả các mục duy nhất từ ​​tất cả ~/.bash_history*các tệp.



1

Tạo một kịch bản có tên script.shnhư dưới đây. Nó tạo ra một tập lệnh có tên X và đặt Y Số dòng lịch sử của bạn vào đó.

#!/bin/bash
SCRIPT_NAME=$1
NUMBER_OF_LINES_BACK=$2

# Enable History in a non interactive shell
HISTFILE=~/.bash_history
set -o history

# echo shabang line and x number of lines of history to new script
echo \#\!\/bin\/bash > $SCRIPT_NAME.sh; history | tail -n $NUMBER_OF_LINES_BACK >> $SCRIPT_NAME.sh;
chmod u+x $SCRIPT_NAME.sh;

# Open the newly created script with vim
vim $SCRIPT_NAME.sh;
~

Sau đó, nếu bạn muốn tạo một kịch bản để hoàn thành một nhiệm vụ có tên là "nhiệm vụ" mà bạn đã thực hiện trong 14 dòng cuối cùng chạy

script.sh task 14

Sau đó làm sạch lịch sử của bạn để tạo ra một kịch bản tốt đẹp!


histtest.sh: 5: set: Illegal option -o history
Ken Sharp

1

Lệnh history bị tắt theo mặc định trên tập lệnh bash, đó là lý do tại sao ngay cả lệnh history cũng không hoạt động trong tệp .sh. để chuyển hướng, vui lòng chuyển hướng tệp bash_history bên trong tệp .sh.

hoặc cơ chế lịch sử cũng có thể được kích hoạt bằng cách đề cập đến tệp lịch sử và thay đổi các tham số thời gian chạy như được đề cập dưới đây

#!/bin/bash
HISTFILE=~/.bash_history
set -o history 

lưu ý: đã đề cập ở trên hai dòng trên đầu tập tin kịch bản. bây giờ lệnh lịch sử sẽ làm việc trong lịch sử.


0

Mỗi người dùng đều có tệp lịch sử của riêng mình, đó là kết quả của lệnh lịch sử. Tiếp tục sử dụng lệnh lịch sử trong tập lệnh shell của bạn, bạn có thể sử dụng tệp lịch sử cho người dùng. Sẽ có một .bash_historytệp trong thư mục chính của người dùng, đó sẽ là tệp lịch sử cho người dùng.


-1

Câu trả lời ngắn gọn :

sử dụng history -pđể thực hiện mở rộng lịch sử một cách rõ ràng.

Một ví dụ sau đây.

Một trường hợp sử dụng xảy ra rất nhiều đối với tôi là:

  • lệnh trước nhận danh sách tên tệp và in ra thiết bị xuất chuẩn,
  • Tôi cần chỉnh sửa các tập tin với vim.

Vì bash của tôi đã được set -o histexpand, thông thường những gì tôi đã làm là gõ

vim $(!!)

để chỉnh sửa các tập tin được liệt kê bởi lệnh trước đó.

Đáng buồn là đôi khi xảy ra lỗi, vì vậy tôi kích hoạt xác minh bằng shopt -s histverify.

Bây giờ tôi có thể xác minh việc mở rộng, với chi phí thêm một Returnkhóa.

Hôm nay tôi muốn gói các chi tiết đó vào một hàm bash vì tôi sử dụng chúng rất nhiều,

function vk() {
    set -o history && set -o histexpand;
    vim -i ~/.viminfok $($(history -p !!));
}

Ở đây tôi sử dụng hai cái lồng nhau command substitution, cái bên trong để mở rộng !!sang lệnh trước, cái bên ngoài để thực thi nó và nhận đầu ra.

Bây giờ tôi có thể đạt được hiệu quả tương tự, chỉ với ba chìa khóa, và một trong số đó là Return!

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.