मुझे एक स्क्रिप्ट लिखने की ज़रूरत है जो एक फ़ाइल को लिखती है कि इस स्क्रिप्ट को कितनी बार निष्पादित किया गया है।
मैं उसे कैसे कर सकता हूँ?
मुझे एक स्क्रिप्ट लिखने की ज़रूरत है जो एक फ़ाइल को लिखती है कि इस स्क्रिप्ट को कितनी बार निष्पादित किया गया है।
मैं उसे कैसे कर सकता हूँ?
जवाबों:
मुझे लगता है कि आप एक एकल फ़ाइल रखना चाहते हैं countfile
जिसमें केवल एक ही संख्या है जो निष्पादन काउंटर का प्रतिनिधित्व करती है।
आप इस काउंटर को शेल चर में पढ़ सकते हैं $counter
जैसे इनमें से किसी एक लाइन का उपयोग करना:
read counter < countfile
counter=$(cat countfile)
$(( EXPRESSION ))
सिंटैक्स का उपयोग करके बश में सरल पूर्णांक जोड़ दिया जा सकता है । तो बस परिणाम हमारे पास वापस लिखें countfile
:
echo "$(( counter + 1 ))" > countfile
आपको शायद अपनी स्क्रिप्ट को उस मामले के लिए भी सुरक्षित करना चाहिए जो countfile
अभी तक मौजूद नहीं है और मूल्य 1 के साथ एक इनिशियलाइज़ेड बनाएं।
पूरी बात इस तरह दिख सकती है:
#!/bin/bash
if [[ -f countfile ]] ; then
read counter < countfile
else
counter=0
fi
echo "$(( counter + 1 ))" > countfile
$(…)
किसी और चीज से पहले निष्पादित किया जाता है (विशेषकर से पहले >
)। लेकिन मैं अक्सर $(cat countfile 2>/dev/null || echo 0)
फ़ाइल मौजूद नहीं होने की स्थिति में एक उचित डिफ़ॉल्ट प्राप्त करने के लिए भाग का उपयोग करता हूं । हम sponge
सुरक्षित होने के लिए :-) जोड़ सकते हैं ।
flock
दौड़ की स्थितियों को रोकने के लिए एक आदेश में उस गिनती को लपेटकर इस उत्तर को बेहतर बनाया जाएगा । देखें unix.stackexchange.com/a/409276
बस स्क्रिप्ट को एक लॉग फ़ाइल बनाने दें, उदाहरण के लिए अंत में अपनी स्क्रिप्ट में एक पंक्ति जोड़ें:
echo "Script has been executed at $(date +\%Y-\%m-\%d) $(date +\%H-\%M-\%S)" >> ~/script.log
इस तरह से आप अपने आप को दिनांक और समय प्रस्तुत करने के तरीके को प्रारूपित कर सकते हैं, लेकिन यदि आप पूरी तरह से पूर्ण तिथि और समय के साथ जाना चाहते हैं (और आपके HH:MM:SS
लिए एक स्वीकार्य प्रारूप है) तो आप बस उपयोग कर सकते हैं:
echo "Script has been executed at $(date +\%F-\%T)" >> ~/script.log
तो आप कर सकते हैं:
wc -l ~/script.log
जो नईलाइन वर्णों को गिनता है और आपको एक अनुमान देता है कि लॉग फ़ाइल के अंदर कितनी लाइनें हैं। उस तक आप लॉग फ़ाइल के भीतर भी देख सकते हैं जब इसे निष्पादित किया गया था। अपनी आवश्यकताओं के लिए इसे अनुकूलित करने के लिए, आप लॉगिंग के लिए उपयोग किए गए पथ और नाम बदल सकते हैं। मैंने यहाँ एक उदाहरण दिया है जो लॉगफ़ाइल को अंदर बचाता है ~
।
इसलिए उदाहरण के लिए आप चाहते हैं कि स्क्रिप्ट इस गिनती को आपके स्क्रिप्ट के अंत में आपके द्वारा जोड़ी गई रेखा से जोड़े, आप अपनी स्क्रिप्ट की शुरुआत में ऐसा कुछ कर सकते हैं:
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"
और अपनी लाइन को स्क्रिप्ट के अंत में बदल दें, जिसमें वह जानकारी भी शामिल है:
echo "Script has been executed $count times at $(date +\%F-\%T)" >> ~/script.log
यह समाधान बाइट कमांडर के उत्तर के समान दृष्टिकोण का उपयोग करता है, लेकिन यह शेल अंकगणित या अन्य बाशिम पर भरोसा नहीं करता है।
exec 2>&3 2>/dev/null
read counter < counter.txt || counter=0
exec 3>&2 3>&-
expr "$counter" + 1 > counter.txt
धारा पुनर्निर्देश
/dev/null
के इनपुट के बाद के पुनर्निर्देशन में त्रुटि संदेश को दबाने के लिए read
यदि काउंटर फ़ाइल अपेक्षित रूप से अनुपलब्ध है),एक अलग काउंटर फ़ाइल में नुकसान हैं:
तो यह उत्तर एक अलग काउंटर फ़ाइल के साथ दूर करता है और अपने आप को bash स्क्रिप्ट में गिनता है!
flock
गारंटी का उपयोग करना कि एक संक्षिप्त समय के लिए दो उपयोगकर्ताओं के लिए एक ही समय में स्क्रिप्ट चलाना संभव नहीं है।#!/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
Videonauth के जवाब देने के लिए इसी प्रकार मैं एक लॉग फ़ाइल जवाब यहां लिखा है: बैश स्क्रिप्ट लेखापरीक्षा निशान बनाए रखने के / फ़ाइलों के प्रवेश करने के लिए पहुँचा हर बार जड़ शक्तियों के साथ इस्तेमाल किया गया लॉग इन करने gedit
या nautilus
।
पकड़ हालांकि gksu
स्क्रिप्ट का उपयोग करने के बजाय नामित है gsu
और pkexec
GUI में sudo का उपयोग करने के "आधुनिक" तरीके को लागू करता है, इसलिए मुझे बताया गया है।
एक अन्य लाभ यह नहीं है कि यह कहता है कि हर बार रूट शक्तियों का उपयोग किया गया था, gedit
लेकिन यह उस फ़ाइल नाम को लॉग करता है जिसे संपादित किया गया था। यहाँ कोड है।
~/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
gsu-log-file-for-gedit
कुछ संपादन के बाद लॉग फ़ाइल की सामग्री :
__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