Saya perlu menulis skrip yang menulis ke file berapa kali skrip ini telah dieksekusi.
Bagaimana saya bisa melakukan itu?
Saya perlu menulis skrip yang menulis ke file berapa kali skrip ini telah dieksekusi.
Bagaimana saya bisa melakukan itu?
Jawaban:
Saya berasumsi Anda ingin memiliki satu file countfile
yang hanya berisi satu nomor tunggal yang mewakili penghitung eksekusi.
Anda dapat membaca penghitung ini ke dalam variabel shell $counter
misalnya menggunakan salah satu dari baris ini:
read counter < countfile
counter=$(cat countfile)
Penambahan integer sederhana dapat dilakukan di Bash sendiri menggunakan $(( EXPRESSION ))
sintaks. Maka cukup tulis kembali hasilnya ke countfile
:
echo "$(( counter + 1 ))" > countfile
Anda mungkin juga harus menjaga skrip untuk kasus yang countfile
belum ada dan membuat skrip yang diinisialisasi dengan nilai 1.
Semuanya mungkin terlihat seperti ini:
#!/bin/bash
if [[ -f countfile ]] ; then
read counter < countfile
else
counter=0
fi
echo "$(( counter + 1 ))" > countfile
$(…)
akan dieksekusi sebelum yang lain (terutama sebelum >
). Tapi saya sering menggunakan $(cat countfile 2>/dev/null || echo 0)
bagian ini untuk mendapatkan default yang wajar jika file tidak ada. Kita bisa menambahkan sponge
:-) agar aman.
flock
perintah untuk mencegah kondisi balapan. Lihat unix.stackexchange.com/a/409276
Biarkan skrip membuat file log, tambahkan misalnya satu baris di skrip Anda di akhir:
echo "Script has been executed at $(date +\%Y-\%m-\%d) $(date +\%H-\%M-\%S)" >> ~/script.log
Dengan cara ini Anda dapat memformat cara Anda sendiri menampilkan tanggal dan waktu, tetapi jika Anda hanya ingin pergi dengan tanggal dan waktu penuh (dan HH:MM:SS
merupakan format yang dapat diterima untuk Anda), Anda juga dapat menggunakan:
echo "Script has been executed at $(date +\%F-\%T)" >> ~/script.log
Maka Anda bisa melakukan:
wc -l ~/script.log
Yang menghitung karakter baris baru dan memberi Anda perkiraan berapa banyak baris di dalam file log. Hingga Anda dapat melihat di dalam file log bahkan ketika itu dijalankan. Untuk menyesuaikannya dengan kebutuhan Anda, Anda dapat mengubah jalur dan nama yang digunakan untuk masuk. Saya baru saja melakukan contoh di sini yang menyimpan logfile di ~
.
Jadi misalnya Anda ingin skrip menambahkan hitungan ini ke baris yang Anda tambahkan di akhir skrip Anda, Anda bisa melakukan sesuatu seperti ini di awal skrip Anda:
count=$(( $(wc -l ~/script.log | awk '{print $1}') + 1 ))
# the next line can be simply skipped if you not want an output to std_out
echo "Script execution number: $count"
Dan ubah baris Anda di akhir skrip ke sesuatu termasuk bahkan informasi itu:
echo "Script has been executed $count times at $(date +\%F-\%T)" >> ~/script.log
Solusi ini menggunakan pendekatan yang sama dengan jawaban Byte Commander tetapi tidak bergantung pada aritmatika shell atau Bashism lainnya.
exec 2>&3 2>/dev/null
read counter < counter.txt || counter=0
exec 3>&2 3>&-
expr "$counter" + 1 > counter.txt
Pengalihan aliran
/dev/null
(untuk menekan pesan kesalahan di pengalihan berikutnya dari input read
perintah jika file counter tidak ada yang diharapkan),File penghitung terpisah memiliki kekurangan:
Jadi jawaban ini tidak menghilangkan file penghitung yang terpisah dan menempatkan hitungan dalam skrip bash itu sendiri!
flock
jaminan bahwa untuk sesaat tidak mungkin bagi dua pengguna untuk menjalankan skrip pada saat yang sama.#!/bin/bash
# NAME: run-count.sh
# PATH: $HOME/bin
# DESC: Written for AU Q&A: /ubuntu/988032/how-can-i-cause-a-script-to-log-in-a-separate-file-the-number-of-times-it-has-be
# DATE: Mar 16, 2018.
# This script run count: 0
# ======== FROM HERE DOWN CAN GO INTO FILE INCLUDED WITH SOURCE COMMAND =======
[ "${FLOCKER}" != "$0" ] && exec env FLOCKER="$0" flock -en "$0" "$0" "$@" || :
# This is useful boilerplate code for shell scripts. Put it at the top of
# the shell script you want to lock and it'll automatically lock itself on
# the first run. If the env var $FLOCKER is not set to the shell script
# that is being run, then execute flock and grab an exclusive non-blocking
# lock (using the script itself as the lock file) before re-execing itself
# with the right arguments. It also sets the FLOCKER env var to the right
# value so it doesn't run again.
# Read this script with entries separated newline " " into array
mapfile -t ScriptArr < "$0"
# Build search string that cannot be named
SearchStr="This script"
SearchStr=$SearchStr" run count: "
# Find our search string in array and increment count
for i in ${!ScriptArr[@]}; do
if [[ ${ScriptArr[i]} = *"$SearchStr"* ]]; then
OldCnt=$( echo ${ScriptArr[i]} | cut -d':' -f2 )
NewCnt=$(( $OldCnt + 1 ))
ScriptArr[i]=$SearchStr$NewCnt
break
fi
done
# Rewrite our script to disk with new run count
# BONUS: Date of script after writing will be last run time
printf "%s\n" "${ScriptArr[@]}" > "$0"
# ========= FROM HERE UP CAN GO INTO FILE INCLUDED WITH SOURCE COMMAND ========
# Now we return you to your original programming....
exit 0
Mirip dengan jawaban Videonauth, saya menulis jawaban file log di sini: Skrip Bash untuk mempertahankan jejak audit / log file yang diakses untuk login setiap kali kekuatan root digunakan dengan gedit
atau nautilus
.
Hasil tangkapannya daripada menggunakan gksu
skrip namanya gsu
dan memanggil pkexec
cara "modern" menggunakan sudo di GUI, jadi saya diberitahu.
Keuntungan lain adalah tidak hanya mengatakan setiap kali kekuatan root digunakan dengan gedit
tetapi mencatat nama file yang telah diedit. Ini kodenya.
~/bin/gsu
:
#!/bin/bash
# Usage: gsu gedit file1 file2...
# -OR- gsu natuilus /dirname
# & is used to spawn process and get prompt back ASAP
# > /dev/null is used to send gtk warnings into dumpster
COMMAND="$1" # extract gedit or nautilus
pkexec "$COMMAND" "${@:2}"
log-file "${@:2}" gsu-log-file-for-"$COMMAND"
/usr/local/bin/log-file
:
#! /bin/bash
# NAME: log-file
# PATH: /usr/local/bin
# DESC: Update audit trail/log file with passed parameters.
# CALL: log-file FileName LogFileName
# DATE: Created Nov 18, 2016.
# NOTE: Primarily called from ~/bin/gsu
ABSOLUTE_NAME=$(realpath "$1")
TIME_STAMP=$(date +"%D - %T")
LOG_FILE="$2"
# Does log file need to be created?
if [ ! -f "$LOG_FILE" ]; then
touch "$LOG_FILE"
echo "__Date__ - __Time__ - ______File Name______" >> "$LOG_FILE"
# MM/DD/YY - hh:mm:ss - "a/b/c/FileName"
fi
echo "$TIME_STAMP" - '"'"$ABSOLUTE_NAME"'"' >> "$LOG_FILE"
exit 0
Isi file log gsu-log-file-for-gedit
setelah beberapa pengeditan:
__Date__ - __Time__ - ______File Name______
11/18/16 - 19:07:54 - "/etc/default/grub"
11/18/16 - 19:08:34 - "/home/rick/bin/gsu"
11/18/16 - 19:09:26 - "/home/rick/bin/gsu"
echo $(( $(cat countfile 2>/dev/null || echo 0) + 1 )) > countfile