Inilah produk akhir yang bekerja pada xterm layar terbagi dari dasarnya shell untuk bekerja hanya dalam beberapa perintah:
Cara yang lebih kasar untuk melakukan ini daripada yang ditunjukkan dalam tangkapan layar mungkin terlihat seperti ini:
PS1='$( { date ; fc -l -0 ; } >${TGT_PTY} )'$PS1
Di mana ${TGT_PTY}
akan menjadi apa pun yang Anda dapatkan dari tty
perintah ketika benar-benar menjalankan shell interaktif di layar di mana Anda ingin output Anda. Atau, sungguh, Anda bisa menggunakan file yang dapat ditulis sama sekali karena pada dasarnya hanya target untuk pengalihan file.
Saya menggunakan sintaks pty untuk pseudo-terminal karena saya menganggap itu adalah xterm dari beberapa jenis, tetapi Anda mungkin dengan mudah mendedikasikan vt - dan sejarah streaming Anda selalu hanya merupakan CTRL-ALT-Fn
kombo kunci. Jika itu aku, aku mungkin menggabungkan dua gagasan dan membuatnya menjadi screen
atau tmux
sesi pada vt khusus ... Tapi aku ngelantur.
Pada mesin yang baru saja boot saya disambut dengan /bin/login
prompt khas pada getty
konsol Linux yang khas . Saya menekan CTRL-ALT-F2
untuk mengakses kmscon
konsol yang kurang umum yang berperilaku lebih seperti xterm
a tty
. Saya memasukkan perintah tty
dan menerima sebagai tanggapan /dev/pts/0
.
Umumnya xterms multipleks perangkat terminal tunggal menjadi banyak menggunakan pseudo-terminal - jadi jika Anda melakukan hal serupa di X11 dengan beralih di antara tab terminal atau windows Anda kemungkinan akan menerima output /dev/pts/[0-9]*
juga. Tetapi konsol terminal virtual yang diakses dengan CTRL-ALT-Fn
kombinasi kunci adalah perangkat terminal yang benar (er) dan karenanya menerima /dev/tty[0-9]*
peruntukannya sendiri .
Inilah sebabnya mengapa setelah masuk ke konsol 2 ketika saya mengetik tty
di prompt jawabannya adalah /dev/pts/0
tetapi ketika saya melakukan hal yang sama pada konsol 1 hasilnya /dev/tty1
. Bagaimanapun, kembali pada konsol 2 saya kemudian lakukan:
bash
PS1='$( { date ; fc -l -0 ; } >/dev/tty1 )'$PS1
Tidak ada efek yang terlihat. Saya terus mengetik beberapa perintah lagi dan kemudian saya beralih ke konsol 1 dengan menekan CTRL-ALT-F1
lagi. Dan di sana saya menemukan entri berulang yang terlihat seperti <date_time>\n<hist#>\t<hist_cmd_string>
untuk setiap perintah yang saya ketikkan pada konsol 2.
Pembatasan langsung menulis ke perangkat terminal, opsi lain dapat terlihat seperti:
TGT_PTY=
mkfifo ${TGT_PTY:=/tmp/shell.history.pipe}
{ echo 'OPENED ON:'
date
} >${TGT_PTY}
Dan mungkin ...
less +F ${TGT_PTY}
Perintah prompt kasar tidak memenuhi spesifikasi Anda - tidak ada string format untuk date
dan tidak ada opsi format fc
baik - tetapi mekanismenya tidak memerlukan banyak: setiap kali prompt Anda membuat perintah riwayat terakhir dan tanggal dan waktu saat ini ditulis untuk yang ${TGT_PTY}
file yang Anda tentukan. Sesederhana itu.
Menonton dan mencetak riwayat shell adalah fc
tujuan utama. Ini adalah built-in shell, meskipun date
tidak. Di zsh
fc
dapat memberikan semua jenis opsi pemformatan mewah, beberapa di antaranya berlaku untuk cap waktu. Dan tentu saja, seperti yang Anda perhatikan di atas, bash
's history
dapat melakukan hal yang sama.
Untuk kepentingan output yang lebih bersih, Anda dapat menggunakan teknik yang saya jelaskan lebih baik di sini untuk mengatur variabel pelacakan persisten di shell saat ini meskipun harus melacak dan memprosesnya dalam subkulit dalam urutan cepat.
Berikut cara portabel memformat dengan spesifikasi Anda:
_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
Saya menerapkan penghitung last_history$_LH
yang hanya melacak pembaruan terbaru sehingga Anda tidak menulis perintah sejarah yang sama dua kali - misalnya hanya untuk menekan enter. Ada sedikit perselisihan yang diperlukan untuk mendapatkan variabel yang bertambah dalam shell saat ini sehingga tetap mempertahankan nilainya meskipun fungsinya disebut dalam subkulit - yang, sekali lagi, lebih baik dijelaskan dalam tautan .
Outputnya seperti <hist#>\t[%F %T]\t<hist_cmd>\n
Tapi itu hanya versi yang sepenuhnya portabel. Dengan bash
itu dapat dilakukan dengan lebih sedikit dan dengan menerapkan shell builtins saja - yang mungkin diinginkan ketika Anda menganggap bahwa ini adalah perintah yang akan berjalan setiap kali Anda menekan [ENTER]
. Berikut ini dua cara:
_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
Atau, menggunakan bash
's history
perintah, Anda dapat menentukan _HIST
fungsi dengan cara ini:
_HIST() { [ -z ${_LH#$1} ] ||
HISTTIMEFORMAT="[%F %T]<tab>" \
history 1 >${TGT_PTY}
printf "(_LH=$1)-$1"
}
Output untuk kedua metode juga terlihat seperti: <hist#>\t[%F %T]\t<hist_cmd>\n
meskipun history
metode ini menyertakan beberapa spasi putih terkemuka. Namun, saya percaya history
cap waktu metode akan lebih akurat karena saya pikir mereka tidak perlu menunggu perintah yang dirujuk untuk menyelesaikan sebelum mendapatkan cap mereka.
Anda dapat menghindari pelacakan keadaan apa pun dalam kedua kasus jika hanya Anda yang entah bagaimana menyaring aliran uniq
- seperti yang mungkin Anda lakukan dengan yang mkfifo
saya sebutkan sebelumnya.
Tetapi melakukannya di prompt seperti ini berarti selalu diperbarui hanya jika perlu hanya dengan tindakan memperbarui prompt. Itu mudah.
Anda mungkin juga melakukan sesuatu yang mirip dengan apa yang Anda lakukan tail
tetapi lebih pada pengaturan
HISTFILE=${TGT_PTY}
fn+1
membandingkan! Terima kasih!