Cron z ludzką twarzą

Każdy, kto kiedykolwiek miał kontakt z cronem wie, że jego zapis – choć prosty i sformalizowany, może sprawić trudności w szybkiej orientacji co i kiedy jest wykonywane.  Poniżej pokażę prosty skrypt, który pozwala wyświetlić tablicę cron w sposób przyjazny nawet laikowi.

Pierwszym krokiem dla przygotowania takiego skryptu jest wyświetlenie tablicy cron dla wskazanego użytkownika. Najprościej zrobić to za pomocą komendy:

crontab -l -u <user>

parametr -l wylistuje na standardowym wyjściu tablicę cron dla użytkownika wskazanego za parametrem -u.

Kiedy mamy już tę tablicę pozostaje nam ją odpowiednio przetworzyć. Ze względu sformalizowany na charakter zapisu tablic cron (tych, którzy nie znają go dokładnie odsyłam do skrótu w wikipedii) bez większych problemów możemy użyć podstawowych filtrów tekstowych np. cut sed.

Aby skorzystać ze skryptu wystarczy pobrać go ze strony – link na końcu posta (można także zmienić rozszerzenie na *.sh), a następnie uruchomić w powłoce:

sh ./human_cron.sh <user>

W wyniku otrzymamy listę komend cron danego użytkownika w formacie opisowym:

-+ komenda /usr/sbin/quotacheck -avug zostanie wykonana codziennie o godzinie 3:00

Dla wygody użytkowania skrypt pomija linie zakomentowane przy pomocy # oraz puste linie tablicy cron, ma też zaimplementowane podstawowe statusy wykonania dla wykonania prawidłowego oraz błędnego, więc można używać go w korelacji z innymi skryptami w oparciu o odczyt statusu wykonania.

Poniżej kod gotowego skryptu w całości (link do pobrania znajduje się pod kodem):

#!/bin/bash
################################################
# bash script                                  #
# author Mikolaj 'Metatron' Niedbala           #
# displays user crontab in human readable form #
# based on `crontab` command                   #
# need to specify user                         #
# licenced GNU/ GPL [made 2013]                #
#################################################

if [[ -z $1 ]]; then
	echo "Podaj uzytkownika CRON, dla ktorego wyswietlic tabele"
	exit 1;
fi;

echo -e "Lista komend do wykonania dla uzytkownika $1\\n"	
crontab -l -u $1 | while read line
	do 
		if [[ ! $line =~ ^\# && ! -z $line ]]; then
			COMBINED_DATE=0
			TIME_str=""
			DATE_str=""

			#explode to values
			COMMAND=`echo "$line" | sed 's/^\(.\{1,8\} \)\{5\}//'`
			MINUTES=`echo "$line" |cut -d" " -f1`
			HOUR=`echo "$line" |cut -d" " -f2`
			MONTH_DAY=`echo "$line" |cut -d" " -f3`
			MONTH=`echo "$line" |cut -d" " -f4`
			WEEK_DAY=`echo "$line" |cut -d" " -f5`

			#command string
			ECHO_str="komenda $COMMAND zostanie wykonana"

			#process values
				#hours
				if [[ ! $HOUR =~ ^\*$ && ! -z $HOUR ]]; then
					if [[ $HOUR =~ ^\*\/[0-9]{1,2}$ && ! -z $HOUR ]]; then
						NUM_HOUR=`echo "$HOUR" |cut -d"/" -f2`;
						HR_str="co $NUM_HOUR godzin";
					elif [[ $HOUR =~ ^[0-9]{1,2}$ && ! -z $HOUR ]]; then
						HR_str="o godzinie $HOUR"
						COMBINED_DATE=1
					elif [[ $HOUR =~ ^[0-9]{1,2}-[0-9]{1,2}$ && ! -z $HOUR ]]; then
						FR_NUM_HOUR=`echo "$HOUR" |cut -d"-" -f1`;
						TO_NUM_HOUR=`echo "$HOUR" |cut -d"-" -f2`;
						HR_str="pomiedzy godzina $FR_NUM_HOUR a $TO_NUM_HOUR"				
					elif [[ $HOUR =~ ^[0-9]{1,2}-[0-9]{1,2}\/[0-9]{1,2}$ && ! -z $HOUR ]]; then
						NUM_HOUR=`echo "$HOUR" |cut -d"/" -f2`;
						HOUR_RANGE=`echo "$HOUR" |cut -d"/" -f1`;
						FR_NUM_HOUR=`echo "$HOUR_RANGE" |cut -d"-" -f1`;
						TO_NUM_HOUR=`echo "$HOUR_RANGE" |cut -d"-" -f2`;
						HR_str="pomiedzy godzina $FR_NUM_HOUR a $TO_NUM_HOUR, co $NUM_HOUR godziny"
					fi;
				else
					HR_str=""
				fi;

				#minutes
				if [[ ! $MINUTES =~ ^\*$ && ! -z $MINUTES ]]; then
					if [[ $MINUTES =~ ^\*\/[0-9]{1,2}$ && ! -z $MINUTES ]]; then
						NUM_MINUTES=`echo "$MINUTES" |cut -d"/" -f2`
						MIN_str="co $NUM_MINUTES minut"
					elif [[ $COMBINED_DATE == 1 ]]; then
						if [[ ! $MINUTES =~ ^\*$ && ! -z $MINUTES ]]; then
							MIN_str="$MINUTES"
						else
							MIN_str="w $MINUTES minucie"
						fi;
					elif [[ $MINUTES =~ ^[0-9]{1,2}-[0-9]{1,2}$ && ! -z $MINUTES ]]; then
						FR_NUM_MINUTES=`echo "$MINUTES" |cut -d"-" -f1`;
						TO_NUM_MINUTES=`echo "$MINUTES" |cut -d"-" -f2`;
						MIN_str="pomiedzy $FR_NUM_MINUTES a $TO_NUM_MINUTES minuta"						
					elif [[ $MINUTES =~ ^[0-9]{1,2}-[0-9]{1,2}\/[0-9]{1,2}$ && ! -z $MINUTES ]]; then
						NUM_MINUTES=`echo "$MINUTES" |cut -d"/" -f2`;
						MINUTES_RANGE=`echo "$MINUTES" |cut -d"/" -f1`;
						FR_NUM_MINUTES=`echo "$MINUTES_RANGE" |cut -d"-" -f1`;
						TO_NUM_MINUTES=`echo "$MINUTES_RANGE" |cut -d"-" -f2`;
						MIN_str="pomiedzy $FR_NUM_MINUTES a $TO_NUM_MINUTES minuta, co $NUM_MINUTES minuty"
					fi;					
				else
					MIN_str=""
				fi;		

				#day of month
				if [[ ! $MONTH_DAY =~ ^\*$ && ! -z $MONTH_DAY ]]; then
					if [[ $MONTH_DAY =~ ^\*\/[0-9]{1,2}$ && ! -z $MONTH_DAY ]]; then
						NUM_MONTH_DAY=`echo "$MONTH_DAY" |cut -d"/" -f2`
						MON_D_str="co $NUM_MONTH_DAY dni"
					elif [[ $MONTH_DAY =~ ^[0-9]{1,2}$ && ! -z $MONTH_DAY ]]; then
						MON_D_str="$MONTH_DAY dnia miesiaca"
					elif [[ $MONTH_DAY =~ ^[0-9]{1,2}-[0-9]{1,2}$ && ! -z $MONTH_DAY ]]; then
						FR_NUM_MONTH_DAY=`echo "$MONTH_DAY" |cut -d"-" -f1`;
						TO_NUM_MONTH_DAY=`echo "$MONTH_DAY" |cut -d"-" -f2`;
						MON_D_str="pomiedzy $FR_NUM_MONTH_DAY a $TO_NUM_MONTH_DAY dniem miesiaca"						
					elif [[ $MONTH_DAY =~ ^[0-9]{1,2}-[0-9]{1,2}\/[0-9]{1,2}$ && ! -z $MONTH_DAY ]]; then
						NUM_MONTH_DAY=`echo "$MONTH_DAY" |cut -d"/" -f2`;
						MONTH_DAY_RANGE=`echo "$MONTH_DAY" |cut -d"/" -f1`;
						FR_NUM_MONTH_DAY=`echo "$MONTH_DAY_RANGE" |cut -d"-" -f1`;
						TO_NUM_MONTH_DAY=`echo "$MONTH_DAY_RANGE" |cut -d"-" -f2`;
						MON_D_str="pomiedzy $FR_NUM_MONTH_DAY a $TO_NUM_MONTH_DAY dniem miesiaca, co $NUM_MONTH_DAY dni"
					fi;						
				else
					MON_D_str=""
				fi;				

				#month
				if [[ ! $MONTH =~ ^\*$ && ! -z $MONTH ]]; then
					if [[ $MONTH =~ ^\*\/[0-9]{1,2}$ && ! -z $MONTH ]]; then
						NUM_MONTH=`echo "$MONTH" |cut -d"/" -f2`
						MON_str="co $NUM_MONTH miesiecy"
					elif [[ $MONTH =~ ^[0-9]{1,2}$ && ! -z $MONTH ]]; then
						MON_str="w $MONTH miesiacu"
					elif [[ $MONTH =~ ^[0-9]{1,2}-[0-9]{1,2}$ && ! -z $MONTH ]]; then
						FR_NUM_MONTH=`echo "$MONTH" |cut -d"-" -f1`;
						TO_NUM_MONTH=`echo "$MONTH" |cut -d"-" -f2`;
						MON_str="pomiedzy $FR_NUM_MONTH a $TO_NUM_MONTH miesiacem"						
					elif [[ $MONTH =~ ^[0-9]{1,2}-[0-9]{1,2}\/[0-9]{1,2}$ && ! -z $MONTH ]]; then
						NUM_MONTH=`echo "$MONTH" |cut -d"/" -f2`;
						MONTH_RANGE=`echo "$MONTH" |cut -d"/" -f1`;
						FR_NUM_MONTH=`echo "$MONTH_RANGE" |cut -d"-" -f1`;
						TO_NUM_MONTH=`echo "$MONTH_RANGE" |cut -d"-" -f2`;
						MON_str="pomiedzy $FR_NUM_MONTH a $TO_NUM_MONTH miesiacem, co $NUM_MONTH miesiecy"
					fi;						
				else
					MON_str=""
				fi;				

				#week day
				if [[ ! $WEEK_DAY =~ ^\*$ && ! -z $WEEK_DAY ]]; then
					if [[ $WEEK_DAY =~ ^\*\/[0-9]{1,2}$ && ! -z $WEEK_DAY ]]; then
						NUM_WEEK=`echo "$WEEK_DAY" |cut -d"/" -f2`
						WEK_str="co $NUM_WEEK dni tygodnia"
					elif [[ $WEEK_DAY =~ ^[0-9]{1,2}$ && ! -z $WEEK_DAY ]]; then
						WEK_str="$WEEK_DAY dnia tygodnia"
					elif [[ $WEEK_DAY =~ ^[0-9]{1,2}-[0-9]{1,2}$ && ! -z $WEEK_DAY ]]; then
						FR_NUM_WEEK_DAY=`echo "$WEEK_DAY" |cut -d"-" -f1`;
						TO_NUM_WEEK_DAY=`echo "$WEEK_DAY" |cut -d"-" -f2`;
						WEK_str="pomiedzy $FR_NUM_WEEK_DAY a $TO_NUM_WEEK_DAY dniem tygodnia"						
					elif [[ $WEEK_DAY =~ ^[0-9]{1,2}-[0-9]{1,2}\/[0-9]{1,2}$ && ! -z $WEEK_DAY ]]; then
						NUM_WEEK_DAY=`echo "$WEEK_DAY" |cut -d"/" -f2`;
						WEEK_DAY_RANGE=`echo "$WEEK_DAY" |cut -d"/" -f1`;
						FR_NUM_WEEK_DAY=`echo "$WEEK_DAY_RANGE" |cut -d"-" -f1`;
						TO_NUM_WEEK_DAY=`echo "$WEEK_DAY_RANGE" |cut -d"-" -f2`;
						MON_str="pomiedzy $FR_NUM_WEEK_DAY a $TO_NUM_WEEK_DAY dniem tygodnia, co $NUM_WEEK_DAY dni"
					fi;						
				else
					WEK_str=""
				fi;

			#generate string for end user
			if [[ $COMBINED_DATE == 1 ]]; then
				if [[ $MIN_str =~ ^[0-9]{1}$ ]]; then
					MIN_str="0$MIN_str"
				fi;					
				TIME_str="$HR_str:$MIN_str, "
			else
				if [[ ! -z $HR_str ]]; then
					TIME_str="$HR_str, "
				else
					TIME_str="$TIME_str$MIN_str, "
				fi;	
			fi;

			if [[ ! -z $WEK_str || ! -z $MON_str || ! -z $MON_D_str ]]; then
				if [[ ! -z $WEK_str ]]; then
					DATE_str="$WEK_str, "
				fi;	
				if [[ ! -z $MON_str ]]; then
					DATE_str="$DATE_str$MON_str, "
				fi;	
				if [[ ! -z $MON_D_str ]]; then
					DATE_str="$DATE_str$MON_D_str, "
				fi;					
			else
				DATE_str="codziennie"
			fi;	

			if [[ $DATE_str =~ ^codziennie$ ]]; then
				echo "-+ $ECHO_str $DATE_str $TIME_str" | sed 's/.\{2\}$//'
			else				
				echo "-+ $ECHO_str $TIME_str $DATE_str" | sed 's/.\{2\}$//'
			fi;	

			echo "--"	
		fi;
done;
exit 0;
Podziel się:

Mikołaj Niedbała

I'm a Poland based IT administrator, linux administrator and IT engineer creating professional IT infrastructure solutions based on Linux and virtual environments.

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *