How to track the sequences in the file changes with Inotifywait - linux

Currently I am monitoring the files by using above code, it works as expected. Basically I am monitoring the opened text files and executing commands.
inotifywait -m -q /home/testDir -e open |
while read path action file; do
if [[ "$file" =~ .*txt$ ]]; then
# execute command
fi
done
I wonder, how can I monitor the sequences of the inotifywait events and execute command.
For example, how can I execute a command or echo something when there is a open,access,close_nowrite event in the directory?
/home/TestDir OPEN test.txt
/home/TestDir ACCESS test.txt
/home/TestDIr CLOSE_NOWRITE,CLOSE test.txt

Related

inotify seems to add a 6 letter code to filenames in its output, before the extension

inotify seems to add a 6 letter code to filenames in its output, before the extension.
For example:
"/path/to/directory/ CLOSE_WRITE,CLOSE filename-HzdVai.lyx"
or with --format "%w%f":
/path/to/directory/filename-HzdVai.lyx
This didn't happen with other scripts and I couldn't find any example of this or why this would happen with googling.
code:
inotifywait -m -r -e close_write --exclude '[^l][^y][^x]$' ~/Routines/* ~/Projects/* | while read path msg name
do
echo "$path $msg $name"
lyx -e pdf "$path$name.lyx"
done
If it's relevant, I am using Ubuntu 20.4.
The intention of the script was to continuously update LyX documents matching pdf files (LyX is a LaTeX-based document processor) so whenever I saved a document it would be compiled automatically
#larks had guessed correctly and tracking move events as well showed that LyX just wrote to the file with the id temporarily, then renamed it.
The final, working, script:
#!/usr/bin/env sh
inotifywait -m -r -e moved_to --exclude '[^l][^y][^x]$' --format "%w%f" ~/Routines/* ~/Projects/* | while read file_path
do
echo "$file_path"
lyx -e pdf "$file_path"
done

How to portable read a text file line by line in bash

For processing a text file in bash line by line, I usually implement a while loop like this:
function doSomething() {
local inputFile="$1"
local fd=""
local line=""
exec {fd}<"$inputFile" # open file
echo "Opened ${inputFile} for read using descriptor ${fd}"
while IFS='' read -r -u $fd line || [[ -n "$line" ]]; do
echo "read = \"$line\""
done
exec {fd}<&- # close file
return 0
}
This works on my Linux but unfortunately not in OSX. For OSX I currently have to change the code to something like this:
exec 3<"$inputFile" # open file
while IFS='' read -r -u 3 line || [[ -n "$line" ]]; do
echo "read = \"$line\""
done
exec 3<&- # close file
But this has the disadvantage, that I have to manage the file descriptor numbers by myself (in the first script, I let bash choose an available file descriptor number).
Did someone have a solution for this which works for both Linux and OSX?
Note that for some reason, I don't want to use piping or I/O redirection to the complete loop like this (because I don't want to execute the loop in a different process):
while IFS='' read -r line || [[ -n "$line" ]]; do
echo "read = \"$line\""
done < "$inputFile"
The last loop will not fork a new process. You can verify that by printing "$BASHPID" in and outside of the loop.
New processes are only created for pipelines. Simple redirections are handled by temporary dups within the bash process.
Feel free to use standard stdin/stdout redirection. It's no more expensive than redirection done with the exec builtin.

Using cat : nothing happens

I have this script :
#!/bin/bash
DIR_TMP=$HOME/.tmp
BIB=$HOME/biblio.bib
inotifywait -m $DIR_TMP -e create -e moved_to |
while read path action file; do
echo $path$file
echo $path$file >> $BIB
cat $path$file >> $BIB
rm $path$file
done
I the while, everything is working fineā€¦ but the cat, which doesn't do anything. Why and how to solve this?
The create and the moved_to events return true when a file is created, but it means neither the writing of the file is over nor there is (already) content in the file.
In my case, it resulted in the cat being executed before the file was written. So I changed the create and moved_to events to a close_write event. And now everything's fine.

Using inotify in a script to monitor a directory

I have written a bash script to monitor a particular directory "/root/secondfolder/" the script is as follows:
#!/bin/sh
while inotifywait -mr -e close_write "/root/secondfolder/"
do
echo "close_write"
done
When I create a file called "fourth.txt" in "/root/secondfolder/" and write stuff to it, save and close it, it outputs the following but it does not echo "close_write":
/root/secondfolder/ CLOSE_WRITE,CLOSE fourth.txt
can someone point me in the right direction?
You are not far away from solution. If you want to use inotifywait in your while statement you should not use -m option. With this option inotifywait never end because it's the monitor option. So you never go into the while.
This should work :
#!/bin/sh
while inotifywait -r -e close_write "/root/secondfolder/"
do
echo "close_write"
done
It turns out all I had to do was pipe the command into a while loop:
!/bin/sh
inotifywait -mqr -e close_write "/root/secondfolder/" | while read line
do
echo "close_write"
done

root running cron task can't read .txt file generated by www-data user

I have a simple php page that writes a file to my server.
// open new file
$filename = "$name.txt";
$fh = fopen($filename, "w");
fwrite($fh, "$name".";"."$abbreviation".";"."$uid".";");
fclose($fh);
I then have a cron job that I know runs as root as test that and need that.
if [[ $EUID -ne 0 ]]; then
echo "This script must be run as root" 1>&2
exit 1
fi
The cronjob is a bash script that can detect the file exists, but it can't seem to read the contents of the file.
#!/bin/bash
######################################################
#### Loop through the files and generate coincode ####
######################################################
for file in /home/test/customcoincode/queue/*
do
echo $file
chmod 777 $file
echo "read file"
while read -r coinfile; do
echo $coinfile
echo "Assign variables from file"
#############################################
#### Set the variables to from the file #####
#############################################
coinName=$(echo $coinfile | cut -f1 -d\;)
coinNameAbreviation=$(echo $coinfile | cut -f2 -d\;)
UId=$(echo $coinfile | cut -f3 -d\;)
done < $file
echo "`date +%H:%M:%S` - $coinName : Your Kryptocoin is being compiled!"
echo $file
echo "copy $coinName file to generated directory"
cp -b $file /home/test/customcoincode/generatedCoins/$coinName.txt
echo "`date +%H:%M:%S` : Delete queue file"
# rm -f $file
done
echo $file recognises the file exists
echo $coinfile is blank
Yet when I nano ./coinfile.txt in terminal I can see clearly there is text in there
I run ls -l and I see that the file has the permissions
-rw-r--r-- 1 www-data www-data
I was under the impression that this would still mean the file can be read by other users?
Do I need to be able to execute the file if i am opening it and reading the contents?
Any advice would be greatly appreciated. I can expand and show my code if you want, but it was working before when I called a bash script to write the file... and that time it would save the file under root user with rwx for most and then could be read. But this then caused other issues in the php page, so is not an option.
You have:
while read -r coinfile; do
...
I see no indication that you're reading from $file. The command
read -r coinfile
will simply read from standard input (the -r merely affects the treatment of backslashes). In a cron job, if I recall correctly, standard input is empty or unavailable, which would explain why $coinfile is empty.
If you actually do read from $file -- for example, if your real code looks something like:
while read -r coinfile; do
...
done <$file
then you need to show us your entire script, or at least a self-contained version of it that exhibits the problem. Actually, you need to show us your entire script whether that's the problem or not.
http://sscce.org/

Resources