Đây là sản phẩm cuối cùng hoạt động trên một xterm màn hình phân chia từ cơ bản mặc định vỏ đến hoạt động chỉ trong một vài lệnh:
Một cách khó khăn hơn để làm điều này hơn là được thể hiện trong ảnh chụp màn hình có thể trông như thế này:
PS1='$( { date ; fc -l -0 ; } >${TGT_PTY} )'$PS1
Nơi nào ${TGT_PTY}
sẽ là bất cứ điều gì bạn nhận được từ tty
lệnh khi thực sự chạy một vỏ tương tác trên màn hình nơi bạn muốn đầu ra của mình. Hoặc, thực sự, bạn có thể sử dụng bất kỳ tệp nào có thể ghi được vì về cơ bản nó chỉ là một mục tiêu để chuyển hướng tệp.
Tôi sử dụng cú pháp pty cho thiết bị đầu cuối giả vì tôi cho rằng đó là một loại xterm nào đó, nhưng bạn có thể dễ dàng dành một vt - và lịch sử phát trực tuyến của bạn luôn chỉ là một CTRL-ALT-Fn
kết hợp chính. Nếu là tôi, tôi có thể kết hợp hai khái niệm và biến nó thành một phiên screen
hoặc tmux
trên một vt chuyên dụng ... Nhưng tôi lạc đề.
Trên một máy mới khởi động, tôi được chào đón với /bin/login
lời nhắc điển hình trên getty
bảng điều khiển Linux điển hình . Tôi nhấn CTRL-ALT-F2
để truy cập vào một kmscon
bảng điều khiển ít điển hình hơn , hoạt động giống như xterm
một tty
. Tôi nhập lệnh tty
và nhận được phản hồi /dev/pts/0
.
Nói chung, xterms ghép một thiết bị đầu cuối thành nhiều thiết bị đầu cuối giả - vì vậy nếu bạn làm điều tương tự trong X11 bằng cách chuyển đổi giữa các tab thiết bị đầu cuối hoặc cửa sổ, bạn cũng có thể nhận được đầu ra /dev/pts/[0-9]*
. Nhưng các bảng điều khiển thiết bị đầu cuối ảo được truy cập với CTRL-ALT-Fn
các tổ hợp phím là các thiết bị đầu cuối đúng (er) và do đó nhận được /dev/tty[0-9]*
chỉ định riêng của chúng .
Đây là lý do tại sao sau khi đăng nhập vào console 2 khi tôi gõ tty
vào dấu nhắc thì phản hồi là /dev/pts/0
nhưng khi tôi làm tương tự trên console 1 thì đầu ra là /dev/tty1
. Trong mọi trường hợp, trở lại trên console 2 tôi sẽ làm:
bash
PS1='$( { date ; fc -l -0 ; } >/dev/tty1 )'$PS1
Không có tác dụng rõ rệt. Tôi tiếp tục gõ thêm một vài lệnh và sau đó tôi chuyển sang giao diện điều khiển 1 bằng cách nhấn CTRL-ALT-F1
lại. Và ở đó tôi tìm thấy các mục lặp đi lặp lại giống như <date_time>\n<hist#>\t<hist_cmd_string>
mọi lệnh tôi đã gõ trên console 2.
Tuy nhiên, việc chặn trực tiếp ghi vào thiết bị đầu cuối, một tùy chọn khác có thể trông giống như:
TGT_PTY=
mkfifo ${TGT_PTY:=/tmp/shell.history.pipe}
{ echo 'OPENED ON:'
date
} >${TGT_PTY}
Và rồi có lẽ ...
less +F ${TGT_PTY}
Lệnh nhắc nhở thô không đáp ứng thông số kỹ thuật của bạn - không có chuỗi định dạng date
và không có tùy chọn định dạng cho fc
một trong hai - nhưng cơ chế của nó không yêu cầu nhiều: mỗi khi dấu nhắc của bạn hiển thị lệnh lịch sử cuối cùng và ngày giờ hiện tại được ghi ra các ${TGT_PTY}
tập tin bạn chỉ định. Nó đơn giản như vậy.
Xem và in lịch sử vỏ là fc
mục đích chính. Đó là một vỏ được tích hợp sẵn, ngay cả khi date
không. Trong zsh
fc
có thể cung cấp tất cả các loại tùy chọn định dạng ưa thích, một số trong đó áp dụng cho tem thời gian. Và tất nhiên, như bạn lưu ý ở trên, chúng bash
ta history
có thể làm như vậy.
Vì lợi ích của đầu ra sạch hơn, bạn có thể sử dụng một kỹ thuật tôi đã giải thích rõ hơn ở đây để đặt biến theo dõi liên tục trong trình bao hiện tại mặc dù phải theo dõi nó và xử lý nó trong các chuỗi con trong chuỗi nhắc nhở.
Đây là một phương tiện di động để định dạng thông số kỹ thuật của bạn:
_HIST() { [ -z ${_LH#$1} ] ||
{ date "+${1}%t[%F %T]"
fc -nl -0
} >${TGT_PTY}
printf "(_LH=$1)-$1"
}
: "${_LH=0}"
PS1='${_LH##*[$(($(_HIST \!)))-9]}'$PS1
Tôi triển khai bộ đếm last_history$_LH
chỉ theo dõi các bản cập nhật mới nhất để bạn không viết cùng một lệnh lịch sử hai lần - ví dụ chỉ để nhấn enter. Có một chút lộn xộn cần thiết để có được biến tăng trong lớp vỏ hiện tại để nó giữ nguyên giá trị của nó mặc dù hàm được gọi trong một lớp con - một lần nữa, được giải thích tốt hơn trong liên kết .
Đầu ra của nó trông giống như <hist#>\t[%F %T]\t<hist_cmd>\n
Nhưng đó chỉ là phiên bản di động hoàn toàn. Với bash
nó có thể được thực hiện với ít hơn và bằng cách chỉ thực hiện các nội dung shell - điều có thể mong muốn khi bạn cho rằng đây là lệnh sẽ chạy mỗi khi bạn nhấn [ENTER]
. Đây là hai cách:
_HIST() { [ -z ${_LH#$1} ] || {
printf "${1}\t[%(%F %T)T]"
fc -nl -0
} >${TGT_PTY}
printf "(_LH=$1)-$1"
}
PROMPT_COMMAND=': ${_LH=0};'$PROMPT_COMMAND
PS1='${_LH##*[$(($(_HIST \!)))-9]}'$PS1
Ngoài ra, sử dụng bash
của history
lệnh, bạn có thể xác định các _HIST
chức năng theo cách này:
_HIST() { [ -z ${_LH#$1} ] ||
HISTTIMEFORMAT="[%F %T]<tab>" \
history 1 >${TGT_PTY}
printf "(_LH=$1)-$1"
}
Đầu ra cho một trong hai phương thức cũng giống như: <hist#>\t[%F %T]\t<hist_cmd>\n
mặc dù history
phương thức này bao gồm một số khoảng trắng hàng đầu. Tuy nhiên, tôi tin rằng history
dấu thời gian của phương thức sẽ chính xác hơn vì tôi không nghĩ rằng họ cần đợi lệnh được tham chiếu hoàn thành trước khi có được dấu của họ.
Bạn có thể tránh theo dõi bất kỳ trạng thái nào trong cả hai trường hợp nếu chỉ bằng cách nào đó bạn lọc luồng với uniq
- như bạn có thể làm với mkfifo
như tôi đã đề cập trước đây.
Nhưng thực hiện nó trong dấu nhắc như thế này có nghĩa là nó luôn được cập nhật ngay khi cần chỉ bằng hành động cập nhật dấu nhắc. Thật đơn giản.
Bạn cũng có thể làm một cái gì đó tương tự như những gì bạn đang làm với tail
nhưng được đặt
HISTFILE=${TGT_PTY}
fn+1
để so sánh! Cảm ơn!