Pete6
Posts: 88
Joined: Sat Nov 24, 2012 4:02 pm

Bash subscripted variable output from for do done loop

Wed Mar 11, 2020 3:29 am

I have a for do done loop and I'd like to get the output onto a set of bash variables similar to out[1], out[2], out[3] and so on.

How may I achieve this please? A google search keeps showing me complex answers often related to array BUT, the output always seems to end up as $out. I need to use the resultant variables later on in my script. The rest of this code snippet does just what I want.

Thanks

Code: Select all

 #!/bin/bash
 2 start=11
 3 hr=60
 4 diff=$[(hr-start)/10]

 6 for ((i=diff; i>=1; i--))
 7 do
 8      out=$[i*10]
10      echo $out
11 done
My favorite programming language is a soldering iron.

hortimech
Posts: 419
Joined: Wed Apr 08, 2015 5:52 pm

Re: Bash subscripted variable output from for do done loop

Wed Mar 11, 2020 9:34 am

You seem to want to use dynamic variable names and to construct these, you will need to use 'eval', try this:

Code: Select all

#!/bin/bash
start=11
hr=60
diff=$(($((hr-start))/10))

count=1
out="out"
for ((i=$diff; i>=1; i--))
do
  OUT=$((i*10))
  eval "$out[$count]=$OUT"
  count=$((count+1))
done
Of course, this does leave you with another problem, $count will depend on the input, so you you will probably need to use another for loop (with $diff) to read the variables.

Pete6
Posts: 88
Joined: Sat Nov 24, 2012 4:02 pm

Re: Bash subscripted variable output from for do done loop

Wed Mar 11, 2020 8:45 pm

Thanks but not quite what I need. Maybe I do not understand what you did.

What I'd like to have are variables that I can use inside the same bash script. The input number may vary from 00 - 59 minutes so I could have any numbers from 1 to 5 or 10 to 50 as an output.

I am writing a script that writes a cron file and I need a job that runs every 10 minutes. However other events intervene making the star time variable as well. I gave the worst case which was a start of 11 meaning I would need 4 variables of 20, 30, 40 and 50 minutes where my cron job runs. It's building a video file every 10 minutes depending on what time the sun sets which is my variable start time. Once I get to the top of the hour, the once-every-10-minutes job kicks in.

This I need a variable diff(1), diff(2)...diff(5) that I could echo diff(3) or echo diff(2) or, use to write my cron file.

Perhaps I should have been clearer or said more yesterday.
My favorite programming language is a soldering iron.

swampdog
Posts: 379
Joined: Fri Dec 04, 2015 11:22 am

Re: Bash subscripted variable output from for do done loop

Wed Mar 11, 2020 10:44 pm

If I'm understanding you correctly then methinks you might want to "man at" (sudo apt-get install at). Set up your cronjob normally but use 'at' to trigger it on sunset.

Start with a wrapper script which defines the environment. 'at', like 'cron' uses a restricted environment so let's make it a bit more like the command line. I've assumed your scripts are going to be in $HOME/bin - doesn't matter, adjust PATH below to taste.

Code: Select all

foo@pi18:~/bin $ cat run.sh 
#!/bin/bash

PATH="$HOME/bin:/usr/bin:/sbin:/bin"
export PATH

#redirect output (debug - no mail)
"$@" >/tmp/z 2>&1

#normal (use 'mail' command)
#"$@"
..'chmod u+x run.sh' above. You can use the above in a crontab as well.

Here's your actual script. It's got its environment from "run.sh" and I envisage you'll have collisions once in a while when the (unchanging) cronjob collides with "sunset" so here's a crude lockfile mechanism..

Code: Select all

foo@pi18:~/bin $ cat myjob 
#!/bin/bash

NAM=$(basename "$0")
LCK="/tmp/$NAM.lck"

[ -f "$LCK" ] && {
	echo "$NAM: Skipped - already running!" 1>&2
	exit 1
}

touch "$LCK"
#sleep 90
echo "Your script here"

rm -f "$LCK"
..'chmod u+x myjob' above. There's actually a better way to handle the lockfile - just about any way is better than the above but I'm keeping it bare bones. There's a shellscript thing called a "trap" which can help but forget that for now. Let's just get something to happen..

Code: Select all

foo@pi18:~/bin $ EDITOR="nano -w" crontab -e
*/1	*	*	*	*	/home/foo/bin/run.sh myjob
..set to once per minute for testing purposes. They key part is setting up the 'at' job. You do it thusly..

Code: Select all

foo@pi18:~/bin $ echo "$HOME/bin/run.sh myjob" | at "now+1 min"
Summary: once you've got the above working all you have to do is have whatever figures out sunset, issue..

Code: Select all

echo "$HOME/bin/run.sh myjob" | at "22:26 2020-03-11"
..with the correct sunset time and adjust "run.sh" so it sends mail again.

The two 'mail' commands you need to know are "n" (next mail) and "q" (exit). Oh and for 'at'..

Code: Select all

foo@pi18:~/bin $ atq
19	Thu Mar 12 00:00:00 2020 a foo
foo@pi18:~/bin $ at -c 19
(output snipped)
foo@pi18:~/bin $ atrm 19
foo@pi18:~/bin $ atq
Simples! (sez the man who hasn't had to use 'at' in years and had to look most stuff up again) ;-)

Pete6
Posts: 88
Joined: Sat Nov 24, 2012 4:02 pm

Re: Bash subscripted variable output from for do done loop

Wed Mar 11, 2020 10:56 pm

If you'd like to take a peek at the project working, go to this url http://75.10.164.105:8082/index.php
Last edited by Pete6 on Wed Mar 11, 2020 11:01 pm, edited 1 time in total.
My favorite programming language is a soldering iron.

Pete6
Posts: 88
Joined: Sat Nov 24, 2012 4:02 pm

Re: Bash subscripted variable output from for do done loop

Wed Mar 11, 2020 10:59 pm

Thanks for your reply. Actually all I need is to know how to have the variables from my for do loop be accessible.

Here is my entire file and it works well apart from this one tiny part that I do not know how to do - yet.

If anybody can just answer my question and give me usable variables out of my for loop that will do the trick. I'm not a programmer, as will be immediately apparent from looking at the attached code. However, it works and I'm on the final stretch and just need a leeetle beet help with this lat bit.

Thanks

Code: Select all

#!/bin/bash
### BEGIN INIT INFO
# Provides:		webcam
# Required-Start:	$remote_fs $syslog $local_fs
# Required-Stop:	$remote_fs $syslog $local_fs
# Default-Start:	2 3 4 5
# Default-Stop:		0 1 6
# Short-Description:	Control raspistill
# Description:		Control raspistill camera time lapse
#			and save images to RAM disk.
### END INIT INFO

BIN="raspistill"
EXE="/usr/bin/$BIN"
[ -x "$EXE" ] || exit 0

SCR="webcam"   # script / service name

# *******************************************************************************
# Setup the Latitude and Longitude of your site

# Location
lat=35.0779911N
lon=80.99140269999998W

# Offsets advance or retard the Day or Twilight times in sunwait.  Anything in between is night
# Offsets.  May be + or - Positive numbers move twilight or sunrise/sunset closer to noon.
# Negative numbers move them away from noon. This adjusts when the camera changes from
# Twilight, Day and Night modes allowing a smoother transition of images from light to
# dark and vice versa.

#     HH:MM
# Shifts camera mode time at  Morning Twilight / Day
twiRise=-00:02

# Shifts camera mode time at Morning Twilight /  Day
SRise=00:02

# Shifts camera mode time at Day / Evening Twilight
SSet=00:02

# Shifts camera mode time at Evening Twilight / NIght
twiSet=-00:20


# *******************************************************************************
echo
echo "AM Twilight Rise: "$twiRise, "Sunrise: "$SRise, "Sunset: "$SSet, "PM Twilight Set: "$twiSet
# *******************************************************************************

# Sunwait to get today's times
AstroRise=$(sunwait list 1 astronomical rise offset $twiRise $lon $lat)
AstroSet=$(sunwait list 1 astronomical set offset $twiSet $lon $lat)
AstroPollRise=$(sunwait poll astronomical offset $twiRise $lon $lat)
AstroPollSet=$(sunwait poll astronomical offset $twiSet $lon $lat)
echo "AstroRise	: "$AstroRise "  AstroSet      : "$AstroSet "  "$AstroPollRise $AstroPollSet

NauticalRise=$(sunwait list 1 nautical rise offset $twiRise $lon $lat)
NauticalSet=$(sunwait list 1 nautical set offset $twiSet $lon $lat)
NauticalPollRise=$(sunwait poll nautical offset $twiRise $lon $lat)
NauticalPollSet=$(sunwait poll nautical offset $twiSet $lon $lat)
echo "NauticalRise	: "$NauticalRise "  NauticalSet 	: "$NauticalSet "  "$NauticalPollRise $NauticalPollSet

CivilRise=$(sunwait list 1 civil rise offset $twiRise $lon $lat)
CivilSet=$(sunwait list 1 civil set offset $twiSet $lon $lat)
CivilPollRise=$(sunwait poll civil offset $twiRise $lon $lat)
CivilPollSet=$(sunwait poll civil offset $twiSet $lon $lat)
echo "CivilRise	: "$CivilRise "  CivilSet 	: "$CivilSet "  "$CivilPollRise $CivilPollSet

SunRise=$(sunwait list 1 sun rise offset $SRise $lon $lat)
SunSet=$(sunwait list 1 sun set offset $SSet $lon $lat)
SunPollRise=$(sunwait poll sun  offset $SRise $lon $lat)
SunPollSet=$(sunwait poll sun  offset $SSet $lon $lat)
echo "SunRise		: "$SunRise "  SunSet	: "$SunSet "  "$SunPollRise $SunPollSet
echo

# Selects the Dawn / Twilight parameter (civil, nautical or astronomical) for cron and for raspistill arguments
# Can be civil, nautical or astronomical.  All thre e Rise Set and Poll must be set.
twilightRise=$CivilRise
twilightSet=$CivilSet
twilightPollRise=$CivilPollRise
twilightPollSet=$CivilPollSet

# Write the times to the file
echo -e $AstroRise"\n"$NauticalRise"\n"$CivilRise"\n"$SunRise"\n"$SunSet"\n"$CivilSet"\n"$NauticalSet"\n"$AstroSet >/home/allsky/daily_parameters

# Get the hours and minutes separated for the four times we are using.
dawntwi=${twilightRise:0:5}; srise=${SunRise:0:5}; sset=${SunSet:0:5}; evetwi=${twilightSet:0:5}

# Chop up Hours and Minutes to get seperate variables.  Get rid of the :
# Dawn
amtH=${dawntwi:0:2}; amtM=${dawntwi:3:2}

# Day
dayH=${srise:0:2}; dayM=${srise:3:2}

# Twilight
twiH=${sset:0:2}; twiM=${sset:3:2}

# Night
nigH=${evetwi:0:2}; nigM=${evetwi:3:2}

# Write the crontab file
echo "# * * * * *">/home/allsky/webcamcron
echo "# * * * * *">>/home/allsky/webcamcron
echo "# * * * * *">>/home/allsky/webcamcron
echo "#0123456789 command to be executed - - - - -">>/home/allsky/webcamcron
echo "# m h dom mon dow command">>/home/allsky/webcamcron
echo "# * * * * *">>/home/allsky/webcamcron
echo "# . . . . .">>/home/allsky/webcamcron
echo "# . . . . ----- Day of week (0 - 7) (Sunday=0 or 7)">>/home/allsky/webcamcron
echo "# . . . ------- Month (1 - 12)">>/home/allsky/webcamcron
echo "# . . --------- Day of month (1 - 31)">>/home/allsky/webcamcron
echo "# . ----------- Hour (0 - 23)">>/home/allsky/webcamcron
echo "# ------------- Minute (0 - 59)">>/home/allsky/webcamcron
echo "# * * * * *">>/home/allsky/webcamcron
echo "# *************************************">>/home/allsky/webcamcron
echo "# Reboot">>/home/allsky/webcamcron
echo "#5 4 * * * root /sbin/shutdown -r +5">>/home/allsky/webcamcron
echo "#">>/home/allsky/webcamcron
echo "# Copy the images every */n minutes">>/home/allsky/webcamcron
echo "*/2 * * * * root /home/allsky/pics/copypicsh">>/home/allsky/webcamcron
echo "#">>/home/allsky/webcamcron
echo "# Setup and make a new Day time movie">>/home/allsky/webcamcron
echo "$amtM $amtH * * * root /home/allsky/pics/newdaymoviesh">>/home/allsky/webcamcron
echo "*/10 $((amtH+1))-$((nigH-1)) * * * root /home/allsky/pics/concatdaysh >/dev/null 2>&1">>/home/allsky/webcamcron
echo "#">>/home/allsky/webcamcron
echo "# Setup and make a new Night time movie">>/home/allsky/webcamcron
echo "$nigM $nigH * * * root /home/allsky/pics/newnightmoviesh">>/home/allsky/webcamcron
echo "*/10 $((nigH+1))-23 * * * root /home/allsky/pics/concatnightsh >/dev/null 2>&1">>/home/allsky/webcamcron
echo "*/10 0-$((amtH-1)) * * * root /home/allsky/pics/concatnightsh >/dev/null 2>&1">>/home/allsky/webcamcron
echo "#">>/home/allsky/webcamcron
echo "# Reload the webcam job for Dawn / Dusk Twilight and Sunrise / Sunset">>/home/allsky/webcamcron
echo "$amtM $amtH * * * root /usr/sbin/service webcam force-reload">>/home/allsky/webcamcron
echo "$dayM $dayH * * * root /usr/sbin/service webcam force-reload">>/home/allsky/webcamcron
echo "$twiM $twiH * * * root /usr/sbin/service webcam force-reload">>/home/allsky/webcamcron
echo "$nigM $nigH * * * root /usr/sbin/service webcam force-reload">>/home/allsky/webcamcron
echo "# $(date)">>/home/allsky/webcamcron
echo "# ">>/home/allsky/webcamcron

chmod 644 /home/allsky/webcamcron
cp /home/allsky/webcamcron /etc/cron.d/webcam
chmod 644 /etc/cron.d//webcam

# Decide what arguments raspistill gets
# Dawn / Day
if [ $SunPollRise = DAY ]; then
  ARG="-ISO 80 -hf -awb greyworld -n -ex auto -w 800 -h 600 -tl 60000 -t 2147483647 -o /run/shm/$SCR.jpg"
  arg1="D"
elif [ $twilightPollRise = NIGHT ]; then
  ARG="-ISO 800 -hf -awb greyworld -n -ex night -ss 6000000 -w 800 -h 600 -tl 60000 -t 2147483647 -o /run/shm/$SCR.jpg"
  arg1="N"
else
  ARG="-ISO 600 -hf -awb greyworld -n -ex auto -w 800 -h 600 -tl 60000 -t 2147483647 -o /run/shm/$SCR.jpg"
  arg1="T"
fi

# Twilight / Night
if [ $SunPollSet = DAY ]; then
  ARG="-ISO 80 -hf -awb greyworld -n -ex auto -w 800 -h 600 -tl 60000 -t 2147483647 -o /run/shm/$SCR.jpg"
  arg1="D"
elif [ $twilightPollSet = NIGHT ]; then
  ARG="-ISO 800 -hf -awb greyworld -n -ex night -ss 6000000 -w 800 -h 600 -tl 60000 -t 2147483647 -o /run/shm/$SCR.jpg"
  arg1="N"
else
  ARG="-ISO 600 -hf -awb greyworld -n -ex auto -w 800 -h 600 -tl 60000 -t 2147483647 -o /run/shm/$SCR.jpg"
  arg1="T"
fi

echo $(date +"%a %D %H:%M") $arg1 $ARG>>/home/allsky/statelog
#echo $ARG>>/home/allsky/daily_parameters
echo -n $arg1>/home/allsky/state
echo $arg1 $ARG

LCK="/var/run/$SCR.pid"   # lock file location

update_lockfile() {
	PID=$(pgrep "$BIN")
	if [ -z "$PID" ]; then
		[ -f "$LCK" ] && [ -w "$LCK" ] && rm -f "$LCK"
	else
		[ -e "$LCK" ] || touch "$LCK"
		[ -f "$LCK" ] && [ -w "$LCK" ] && echo "$PID" > "$LCK"
	fi
}

do_start() {
	$EXE $ARG &
	update_lockfile
}

do_stop() {
	killall -q "$BIN"
	update_lockfile
}

case "$1" in
	status)
		echo -n "Service $SCR is "
		update_lockfile
		if [ -z "$PID" ]; then
			echo "not running." >&2
			exit 3
		else
			echo "running."
		fi
		;;
	start)
		echo -n "Starting service $SCR..."
		update_lockfile
		if [ -n "$PID" ]; then
			echo "already started." >&2
			exit 4
		else
			do_start
			echo "done."
		fi
		;;
	stop)
		echo -n "Stopping service $SCR..."
		update_lockfile
		if [ -z "$PID" ]; then
			echo "already stopped." >&2
			exit 5
		else
			do_stop
			echo "done."
		fi
		;;
	restart|force-reload)
		echo -n "Restarting service $SCR..."
		do_stop
		if [ -n "$PID" ]; then
			echo "failed to stop." >&2
			exit 6
		else
			do_start
			if [ -z "$PID" ]; then
				echo "failed to start." >&2
				exit 7
			else
				echo "done."
			fi
		fi
		;;
	*)
		echo "Usage: $0 {status|start|stop|restart|force-reload}" >&2
		exit 8
		;;
esac
exit 0
My favorite programming language is a soldering iron.

hortimech
Posts: 419
Joined: Wed Apr 08, 2015 5:52 pm

Re: Bash subscripted variable output from for do done loop

Thu Mar 12, 2020 11:06 am

Pete6 wrote:
Wed Mar 11, 2020 8:45 pm
Thanks but not quite what I need. Maybe I do not understand what you did.

This I need a variable diff(1), diff(2)...diff(5) that I could echo diff(3) or echo diff(2) or, use to write my cron file.
You cannot have '$diff(1)" etc. You (it seems) want to create dynamic variable names:
$diff(1)
$diff(2)

and so on
The only way to do this is to use 'eval' and you cannot use '( )'

Updated script with comments and example extra for loop:

Code: Select all

#!/bin/bash

# example start number, could be different
start=11
# hour in minutes ?
hr=60

# set 'diff'
D=$(($((hr-start))/10))

# the new variables number to start from
count=1

# the new variables 'name'
diff="diff"

# the countdown for loop
for ((i=$D; i>=1; i--))
do
  # set $OUT to $1 multiplied by 10
  OUT=$((i*10))
  # create the variable name and set it to contain $OUT
  # e.g if this was the first time through: $diff[1] containing '40'
  eval "$diff[$count]=$OUT"
  # add one to $count
  count=$((count+1))
done

# print the variables
for ((i=$D; i>=1; i--))
do
  echo "The variable \${diff[$i]} contains ${diff[$i]}"
done

This will produce variable names such as : ${diff[1]}

Pete6
Posts: 88
Joined: Sat Nov 24, 2012 4:02 pm

Re: Bash subscripted variable output from for do done loop

Thu Mar 12, 2020 1:57 pm

THAT is fantastic. It is very elegant a exactly what I need. It helps that it also works perfectly .Thank you.

I did some (well, a lot) Googling and it seems that certainly piping "|" and most likely for loops start a sub-shell to work within and variables within the sub-shell are thrown away when the sun-shell closes.

So now I understand why what I was trying to do could never work. I re-wrote it using if loops and that works like yours does but it is far less flexible and my code looks terrible.

Thanks again
Pete

P.S. Did you get a look at the camera? I am an amateur astronomer and I am building and AlSky Camera. This takes a picture of the sky once a minute. You can thus see an immediate image of the sky anytime. Every 2 minutes it copies a pic to a directory and every 10 concatenates these images into a day or night movie and that is what you see.

The Raspberry Pi camera 2 is very good but one exposure does not fit all sky and light conditions and I need three different settings for raspistill (night, twilight and day). This is where some complexity has crept in. However It is very nearly working with only a few bugs left to squash.

Once completed and working, I will make it available to anyone who wants it. It has cost me about 100 quid and this is an order of magnitude les than commercial devices which, admittedly do have better cameras. It's been a fun project.
My favorite programming language is a soldering iron.

Pete6
Posts: 88
Joined: Sat Nov 24, 2012 4:02 pm

Re: Bash subscripted variable output from for do done loop

Thu Mar 12, 2020 4:39 pm

During my searches I came across this little gem. https://manpages.debian.org/jessie/cron/cron.8.en.html

An extract shows this:
As described above, the files under these directories have to be pass some sanity checks including the following: be executable, be owned by root, not be writable by group or other and, if symlinks, point to files owned by root. Additionally, the file names must conform to the filename requirements of run-parts: they must be entirely made up of letters, digits and can only contain the special signs underscores ('_') and hyphens ('-'). Any file that does not conform to these requirements will not be executed by run-parts. For example, any file containing dots will be ignored. This is done to prevent cron from running any of the files that are left by the Debian package management system when handling files in /etc/cron.d/ as configuration files (i.e. files ending in .dpkg-dist, .dpkg-orig, and .dpkg-new).
Thus filenames containing "." will be ignored by crontabs in /etc/cron.d. FIles with "." in the filename wil work fine in /var/spool/crontabs according to this document.

I have tested this on two PIs running Stretch and it seems to be the case.
My favorite programming language is a soldering iron.

jbudd
Posts: 1358
Joined: Mon Dec 16, 2013 10:23 am

Re: Bash subscripted variable output from for do done loop

Fri Mar 13, 2020 12:36 am

I did some (well, a lot) Googling and it seems that certainly piping "|" and most likely for loops start a sub-shell to work within and variables within the sub-shell are thrown away when the sun-shell closes.
You are right that environment changes within a sub shell are lost when it exits.

However, for loops are not implemented with sub shells:

Code: Select all

pi@BlackPi:~ $ cat foo
#! /bin/bash

i=1

for f in 1 2 3 4 5   # ie loop 5 times
do
  echo $i
  (( i = i + 1 ))
done
echo Out of loop $i
pi@BlackPi:~ $ ./foo
1
2
3
4
5
Out of loop 6

And perhaps I'm misunderstanding something but here is an array constructed in a for loop and then used. No eval.

Code: Select all

pi@BlackPi:~ $ cat wibble
#! /bin/bash

declare -a myarray
i=1
for f in egg bacon cheese beans
do
   myarray[$i]=$f
   (( i = i + 1 ))
done

echo Second element ${myarray[2]}
echo Whole array ${myarray[@]}
declare -p myarray        # Show me what the array consists of
pi@BlackPi:~ $ ./wibble
Second element bacon
Whole array egg bacon cheese beans
declare -a myarray=([1]="egg" [2]="bacon" [3]="cheese" [4]="beans")

Pete6
Posts: 88
Joined: Sat Nov 24, 2012 4:02 pm

Re: Bash subscripted variable output from for do done loop

Fri Mar 13, 2020 1:39 am

You are probably be right about the for loop not being a sub-shell. I do not know enough about Linux or Bash to know. I appreciate the alternative solution. Right now my project is working fine. Well almost.

I have a cronjob error that I do not understand.

Code: Select all

cron[372]: (*system*webcam) ERROR (Syntax error, this crontab file will be ignored)
webcam is my shell script that is being run by cron. This listing was pulled from grep webcam /var/log/syslog |less

I am not sure if the error is from my script file or from the crontab file. The problem is that the crontab file is written by the shell scrip webcam file.

the webcam script file runs fine and is constantly being tweaked by me.
My favorite programming language is a soldering iron.

User avatar
scruss
Posts: 3155
Joined: Sat Jun 09, 2012 12:25 pm
Location: Toronto, ON
Contact: Website

Re: Bash subscripted variable output from for do done loop

Fri Mar 13, 2020 2:00 am

Pete6 wrote:
Thu Mar 12, 2020 4:39 pm
… Thus filenames containing "." will be ignored by crontabs in /etc/cron.d.
I'm just wondering if cron is the best tool for your needs. Modifying crontab files multiple times a day isn't really what it's for. Cron runs with a reduced environment and uses a very simple shell. It has a very steep learning curve, as you've been finding out.

There are lots of ways to schedule events on Linux:
  • at is like a one-shot cron. It's very easy to add, remove and list queued jobs. It's not installed by default, so you'll need to do sudo apt install at
  • remind is the Swiss Army Thermal Lance of calendar programs. It's immensely capable, and can do some scheduling/calendar things that no other calendar can do. It has sunset/sunrise event tracking built-in. It has good documentation and a small but dedicated user base. More details: Remind.
I'm sure there are other options, but those are what come to mind.
‘Remember the Golden Rule of Selling: “Do not resort to violence.”’ — McGlashan.
Pronouns: he/him

Pete6
Posts: 88
Joined: Sat Nov 24, 2012 4:02 pm

Re: Bash subscripted variable output from for do done loop

Fri Mar 13, 2020 2:23 am

You may be right. I am reluctant to change right now as I am very much a beginner with Linux. I need to learn enough to ask questions if you see what I mean.

Here's my cron file that is generated by my shell script named webcam. This is regenerated by the script file every time the webcam file is run. Of course it also regenerates every time cron runs the webcam file which is currently 4 times a day.

I currently run this file from /etc/cron.d but have recently learned that it might be better in /var/spool//cron/crontabs. Which is best? Remember that the Pi is located on the top of my roof gutter so is unlikely to be used for anything else. The whole thing runs in root.

Code: Select all

# * * * * *
# * * * * *
# * * * * *
#0123456789 command to be executed - - - - -
# m h dom mon dow command
# * * * * *
# . . . . .
# . . . . ----- Day of week (0 - 7) (Sunday=0 or 7)
# . . . ------- Month (1 - 12)
# . . --------- Day of month (1 - 31)
# . ----------- Hour (0 - 23)
# ------------- Minute (0 - 59)
# * * * * *
# *************************************
# Reboot
#5 4 * * * root /sbin/shutdown -r +5
#
# Copy the images every */n minutes
*/3 * * * * root /home/allsky/pics/copypicsh
#
# Setup and make a new Day time movie
12 07 * * * root /home/allsky/pics/newdaymoviesh
20 07 * * * root /home/allsky/pics/concatdaysh
30 07 * * * root /home/allsky/pics/concatdaysh
40 07 * * * root /home/allsky/pics/concatdaysh
50 07 * * * root /home/allsky/pics/concatdaysh
*/10 8-19 * * * root /home/allsky/pics/concatdaysh
#
# Setup and make a new Night time movie
13 20 * * * root /home/allsky/pics/newnightmoviesh
20 20 * * * root /home/allsky/pics/concatnightsh
30 20 * * * root /home/allsky/pics/concatnightsh
40 20 * * * root /home/allsky/pics/concatnightsh
50 20 * * * root /home/allsky/pics/concatnightsh
*/10 0-6 * * * root /home/allsky/pics/concatnightsh
*/10 21-23 * * * root /home/allsky/pics/concatnightsh
#
# Reload the webcam job for Dawn / Dusk Twilight and Sunrise / Sunset
12 07 * * * root /usr/sbin/service webcam reload
40 07 * * * root /usr/sbin/service webcam reload
27 19 * * * root /usr/sbin/service webcam reload
13 20 * * * root /usr/sbin/service webcam reload
# 
# Thu Mar 12 20:22:48 EDT 2020
# 
It is written by this bit of code

Code: Select all

# Write the crontab file
echo "# * * * * *">>/home/allsky/webcamcron
echo "# * * * * *">>/home/allsky/webcamcron
echo "# * * * * *">>/home/allsky/webcamcron
echo "#0123456789 command to be executed - - - - -">>/home/allsky/webcamcron
echo "# m h dom mon dow command">>/home/allsky/webcamcron
echo "# * * * * *">>/home/allsky/webcamcron
echo "# . . . . .">>/home/allsky/webcamcron
echo "# . . . . ----- Day of week (0 - 7) (Sunday=0 or 7)">>/home/allsky/webcamcron
echo "# . . . ------- Month (1 - 12)">>/home/allsky/webcamcron
echo "# . . --------- Day of month (1 - 31)">>/home/allsky/webcamcron
echo "# . ----------- Hour (0 - 23)">>/home/allsky/webcamcron
echo "# ------------- Minute (0 - 59)">>/home/allsky/webcamcron
echo "# * * * * *">>/home/allsky/webcamcron
echo "# *************************************">>/home/allsky/webcamcron
echo "# Reboot">>/home/allsky/webcamcron
echo "#5 4 * * * root /sbin/shutdown -r +5">>/home/allsky/webcamcron
echo "#">>/home/allsky/webcamcron
echo "# Copy the images every */n minutes">>/home/allsky/webcamcron
echo "*/$cap * * * * root /home/allsky/pics/copypicsh">>/home/allsky/webcamcron
echo "#">>/home/allsky/webcamcron
echo "# Setup and make a new Day time movie">>/home/allsky/webcamcron
echo "$amtM $amtH * * * root /home/allsky/pics/newdaymoviesh">>/home/allsky/webcamcron
# print the DAY fill-in variables
for ((i=$D-1; i>=1; i--))
do
  echo "${Ddiff[i]} $amtH * * * root /home/allsky/pics/concatdaysh">>/home/allsky/webcamcron
done
echo "*/$per $((amtH+1))-$((nigH-1)) * * * root /home/allsky/pics/concatdaysh">>/home/allsky/webcamcron
echo "#">>/home/allsky/webcamcron
echo "# Setup and make a new Night time movie">>/home/allsky/webcamcron
echo "$nigM $nigH * * * root /home/allsky/pics/newnightmoviesh">>/home/allsky/webcamcron
# print the NIGHT fill-in variables
for ((j=$N-1; j>=1; j--))
do  echo "${Ndiff[j]} $((nigH)) * * * root /home/allsky/pics/concatnightsh">>/home/allsky/webcamcron
done
echo "*/$per 0-$((amtH-1)) * * * root /home/allsky/pics/concatnightsh">>/home/allsky/webcamcron
echo "*/$per $((nigH+1))-23 * * * root /home/allsky/pics/concatnightsh">>/home/allsky/webcamcron
echo "#">>/home/allsky/webcamcron
echo "# Reload the webcam job for Dawn / Dusk Twilight and Sunrise / Sunset">>/home/allsky/webcamcron
echo "$amtM $amtH * * * root /usr/sbin/service webcam reload">>/home/allsky/webcamcron
echo "$dayM $dayH * * * root /usr/sbin/service webcam reload">>/home/allsky/webcamcron
echo "$twiM $twiH * * * root /usr/sbin/service webcam reload">>/home/allsky/webcamcron
echo "$nigM $nigH * * * root /usr/sbin/service webcam reload">>/home/allsky/webcamcron
echo "# ">>/home/allsky/webcamcron
echo "# $(date)">>/home/allsky/webcamcron
echo "# ">>/home/allsky/webcamcron

chmod 644 /home/allsky/webcamcron
cp /home/allsky/webcamcron /etc/cron.d/webcam
chmod 644 /etc/cron.d//webcam
It was actually easy enough to learn cron's syntax. It is very logical but unforgiving. It is also hard to debug until you learn its ways. There is a little bit of conditional involved in getting the cron file right each time and it was this that made me ask for old BASIC (Yup, learned that when it had line numbers) subscripting. I know better now but I'll never be a programmer.
My favorite programming language is a soldering iron.

Pete6
Posts: 88
Joined: Sat Nov 24, 2012 4:02 pm

Re: Bash subscripted variable output from for do done loop

Sun Mar 15, 2020 5:37 pm

@scruss, I have started playing with at. It was not on my Pi so I installed it. I seems to be a different approach to what I am doing now but that is not a problem. I think I shall be able to dispense with running a service job and just have at run stuff for me from a file. It is going to take me a couple of day to set it up but since I am in self quarantine right now (age 74 with a pulmonary problem) I have time in between building my emergency pulmonary ventilator.

Thank you very much for pointing me in this direction.
My favorite programming language is a soldering iron.

Return to “Beginners”