[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: nother bash question



On Monday 13 June 2016 06:30:39 Thomas Schmitt wrote:

> Hi,
>
> i wrote:
> > > Is ${InMail} supposed to be empty ?
It is not supposed to be.  Empty only if I kill it with  a killall in practice.
>
> Gene Heskett wrote:
> > That is set by inotifywait's return of the name of the file that
> > procmail just closed.
>
> Hmm. I don't have inotifywait installed.
> According to http://linux.die.net/man/1/inotifywait it should put out
> lines like
>   CLOSE_WRITE:CLOSE goodfile

No, if the argument is set correctly, and the %f in the arguments at 
launch time are set, it returns only the name of the file that was 
closed, or it can be set to watch only the closing of files written to
as in this case.

In case someone wants to try it out, here is the script as it exists 
at this instant but it makes assumptions that you are on a first name
basis with both fetchmail and procmail too.  This completely offloads
the mail fetching by your email agent, in this case kmail, so  its
getmail functions are automatic, on demand and fractional seconds to do,
paced by the -d time argument in your ~/.fetchmailrc:
=============================
#!/bin/bash
set -x
# this was a test, was /bin/sh above, but /bin/sh is a softlink 
# to /bin/dash, which failed my testing
# REQUIRES your distros inotify-tools package, assumes kde/kmail in use
# but might be adaptable to other agents too
# requires a ~/log directory, so mkdir it before running this
# you will also need to either do the housekeeping of this file, or
# figure out how to make logrotate do it for you.
# when launching this, all output MUST be redirected >/dev/null 2>1 &
# like "/path/to/mailwatcher >/dev/null 2>&1 &"
# As inotifywait is not silent on launch even with the -q option
WatchDir=/var/spool/mail/
# Setup temporary log
Log=mail.log
Mlog=~/log
# in case it doesn't exist, make it
touch ${Mlog}/${Log}
# the command to send over dbus/dcop to make kmail pull the mailfile in /var/spool/mail

# First set method
Method=dcop
if [[ ${Method} = 'dbus' ]]
then
	Cmd="/usr/bin/qdbus org.kde.kmail /KMail org.kde.kmail.kmail.checkMail"
fi
if [[ ${Method} = 'dcop' ]]
then
# or for dcop, use:
	Cmd="/opt/trinity/bin/dcop kmail KMailIface checkMail"
fi

#  Now, do forever
while :
do
	sleep 2
	if [ $(pidof -s kmail) ]
	then
		echo -n "Kmail is running " >>${Mlog}/${Log}
		date -R >>${Mlog}/${Log}
		sleep 1 # delay to give kmail a chance to settle in
		# only start fetchmail once!
		if [ $(pidof -s fetchmail) ]
		then
			sleep 1
		else
			echo -n "starting fetchmail at " >>${Mlog}/${Log}
			fetchmail -d 180 -t 60 --fetchmailrc /home/gene/.fetchmailrc >>${Mlog}/${Log} &
			date -R >>${Mlog}/${Log}
		fi
		sleep 1 # delay to give kmail a chance to get its dcop/dbus sockets setup?
		$cmd #probably superfolous
		while [ $(pidof -s kmail) ]
		do
			# I've found that stderr needs dumped to /dev/null, so
			InMail=`/usr/bin/inotifywait -q -e close_write --format %f ${WatchDir}` 2>&1 >/dev/null 		
			# and here it sits until inotifywait exits because of an incoming mail
			# and sometime later it will exit, setting $InMail to something.

			if test "${InMail}" = "gene"
			then
				$Cmd
				sleep 2
				# log it
				date -R >>${Mlog}/${Log}
				echo ${InMail} >>${Mlog}/${Log}
			elif test "${InMail}" = "gene-from_linda"
			then
				$Cmd
				sleep 2
				# log it
				date -R >>${Mlog}/${Log}
				echo ${InMail} >>${Mlog}/${Log}
			elif test "${InMail}" = "amanda"
			then
				$Cmd
				sleep 2
				# log it
				date -R >>${Mlog}/${Log}
				echo ${InMail} >>${Mlog}/${Log}
			fi

		done
		# we don't have a pidof kmail, log that its gone
		echo -n "Kmails pid is missing - it has stopped ">>${Mlog}/${Log}
		date -R >>${Mlog}/${Log}
		# Now, kill fetchmail too, and this is ok to do
		killall fetchmail
		# get rid of a waiting inotifywait, but this is not inotifywait instance
		# sensitive and may kill the one for cocoprint.
		killall inotifywait
	fi
	# and should be back in the outer loop, waiting for a kmail PID
done
=============================
fetchmail fires off a session of mailfilter, which can nuke undesirables
on the server so fetchmail never sees them, then fetchmail does the 
pulling, hands it off to procmail for some deaths and diversions, and 
puts what survives into one of 4 named files in /var/spool/mail/
That action then triggers inotifywait, which returns the name of the 
file to this script.

> I guess you pick the second word or the line end of such a line.
> It would be interesting to see how you do this.
See above, and inotifywait's man page, its handier than sliced bread or
bottled beer IMNSHO.
> > I should probably clear InName to "", but inotifywait has been
> > coping with that for about a decade :)
>
> All is well as long as ${InMail} is perceived by the shell parser as
> a single shell word. (I.e. a text snippet which the shell parser
> recognizes as a unit.)
>
> So i assume that the problem is in the text which your script picks
> from the inotifywait reply.
> Add to the script some commands which print the line and the text it
> picks. Then you get hints what might go wrong and some an to play with
> in the shell dialog line.
>
Thats called the set -x in line 2 :) When I am happy, it goes away.

> ---------------------------------------------------------------------
>
> Detour into theory:
> > > > bin/mailwatcher: line 66: test: =: unary operator expected
>
> tomas@tuxteam.de wrote:
> > One could argue "unary operator expected" is a strange way to
> > restate this.
>
> It's the way how the gild of land surveyors and bean counters
> expresses itself:
> Unary operators are for example the logical negation ("not") or the
> arithmetic sign ("-").
> Binary operators are logical conjunction ("and") or arithmetic
> subtraction ("-" again (nobody promised math to be straightforward)).
>
> Since there is only one non-operator given ("gene"), the parser is
> unwilling to accept any binary operator. The message is then just an
> indication that the programmer was either to concentrated on the
> job or that the parser of test does not know enough about its boss
> program.
> A user-aware programmer of a boss-program-aware parser could well
> report: "Operator '=' expects two operands. Only one is given."
>
> Beware: '=' without any operand is considered to be syntactically
>         correct and evaluates as "true":
>
>   $ test =
>   $ echo $?
>   0
>
> because of:
>  
> https://www.gnu.org/software/coreutils/manual/html_node/test-invocatio
>n.html#test-invocation "If expression is omitted, test returns false.
> If expression is a single argument, test returns false if the argument
> is null and true otherwise."
>
> I guess the founders of Unix introduced this rule when a byte of
> storage was worth more than a dollar.
>
>
> Have a nice day :)
>
> Thomas

Thanks Thomas.

Cheers, Gene Heskett
-- 
"There are four boxes to be used in defense of liberty:
 soap, ballot, jury, and ammo. Please use in that order."
-Ed Howdershelt (Author)
Genes Web page <http://geneslinuxbox.net:6309/gene>


Reply to: