Ich muss ein Skript schreiben, das in eine Datei schreibt, wie oft dieses Skript ausgeführt wurde.
Wie kann ich das machen?
Ich muss ein Skript schreiben, das in eine Datei schreibt, wie oft dieses Skript ausgeführt wurde.
Wie kann ich das machen?
Antworten:
Ich gehe davon aus, dass Sie eine einzelne Datei haben möchten, die countfile
nur eine einzige Nummer enthält, die den Ausführungszähler darstellt.
Sie können diesen Zähler in eine Shell-Variable einlesen, $counter
z. B. mit einer der folgenden Zeilen:
read counter < countfile
counter=$(cat countfile)
Einfache Ganzzahladditionen können in Bash selbst mithilfe der $(( EXPRESSION ))
Syntax vorgenommen werden. Dann schreiben Sie einfach das Ergebnis zurück an countfile
:
echo "$(( counter + 1 ))" > countfile
Sie sollten Ihr Skript wahrscheinlich auch für den Fall schützen, der countfile
noch nicht vorhanden ist, und dann ein Skript erstellen, das mit dem Wert 1 initialisiert wurde.
Das Ganze könnte so aussehen:
#!/bin/bash
if [[ -f countfile ]] ; then
read counter < countfile
else
counter=0
fi
echo "$(( counter + 1 ))" > countfile
$(…)
vor irgendetwas anderem ausgeführt wird (besonders vor dem >
). Aber ich benutze das $(cat countfile 2>/dev/null || echo 0)
Teil oft , um einen vernünftigen Standard zu erhalten, falls die Datei nicht existiert. Wir könnten ein sponge
:-) hinzufügen , um sicher zu gehen.
flock
Befehl eingeschlossen wird, um Rennbedingungen zu verhindern. Siehe unix.stackexchange.com/a/409276
Lassen Sie das Skript einfach eine Protokolldatei erstellen und fügen Sie am Ende beispielsweise eine Zeile in Ihr Skript ein:
echo "Script has been executed at $(date +\%Y-\%m-\%d) $(date +\%H-\%M-\%S)" >> ~/script.log
Auf diese Weise können Sie die Darstellung von Datum und Uhrzeit selbst formatieren. Wenn Sie jedoch nur ein vollständiges Datum und eine vollständige Uhrzeit verwenden möchten (und HH:MM:SS
ein für Sie akzeptables Format haben), können Sie auch einfach Folgendes verwenden:
echo "Script has been executed at $(date +\%F-\%T)" >> ~/script.log
Dann könnten Sie tun:
wc -l ~/script.log
Dies zählt die Zeilenumbruchzeichen und gibt Ihnen eine Schätzung, wie viele Zeilen sich in der Protokolldatei befinden. Bis dahin können Sie in der Protokolldatei sehen, auch wenn sie ausgeführt wurde. Um es an Ihre Bedürfnisse anzupassen, können Sie die Pfade und Namen ändern, die für die Protokollierung verwendet werden. Ich habe hier nur ein Beispiel gemacht, in dem die Protokolldatei gespeichert wird ~
.
Wenn Sie beispielsweise möchten, dass das Skript diese Anzahl zu der Zeile hinzufügt, die Sie am Ende Ihres Skripts hinzugefügt haben, können Sie am Anfang Ihres Skripts Folgendes tun:
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"
Und ändern Sie Ihre Zeile am Ende des Skripts in etwas, das auch diese Informationen enthält:
echo "Script has been executed $count times at $(date +\%F-\%T)" >> ~/script.log
Diese Lösung verwendet den gleichen Ansatz wie die Antwort von Byte Commander, basiert jedoch nicht auf Shell-Arithmetik oder anderen Bashismen.
exec 2>&3 2>/dev/null
read counter < counter.txt || counter=0
exec 3>&2 3>&-
expr "$counter" + 1 > counter.txt
Die Stream-Umleitungen
/dev/null
(um die Fehlermeldung bei der nachfolgenden Umleitung der read
Befehlseingabe zu unterdrücken, wenn die Zählerdatei erwartungsgemäß fehlt).Eine separate Zählerdatei hat Nachteile:
Diese Antwort beseitigt also eine separate Zählerdatei und fügt die Zählung in das Bash-Skript selbst ein!
flock
garantiert, dass es für einen kurzen Moment nicht möglich ist, dass zwei Benutzer das Skript gleichzeitig ausführen.#!/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
Ähnlich wie bei Videonauths Antwort habe ich hier eine Antwort auf eine Protokolldatei geschrieben: Bash-Skript zum Verwalten des Prüfpfads / Protokolls von Dateien, auf die jedes Mal zugegriffen wird , wenn bei gedit
oder mit Root-Potenzen mit oder protokolliert wird nautilus
.
Der Haken ist jedoch, anstatt gksu
das Skript zu verwenden, benannt zu sein gsu
und pkexec
die "moderne" Art der Verwendung von sudo in der GUI aufzurufen, so wird mir gesagt.
Ein weiterer Vorteil ist, dass nicht nur jedes Mal angegeben wird, wenn Root-Kräfte verwendet wurden, gedit
sondern auch der bearbeitete Dateiname protokolliert wird. Hier ist der Code.
~/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
Inhalt der Protokolldatei gsu-log-file-for-gedit
nach einigen Änderungen:
__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