I am trying to extract the logs b/w two given dates. the code is working fine if I specify the date like this Apr 02 15:21:28, I mean if know time with exact min and second, But code gets failed with I pass value like this
from Apr 02 15* to Apr 04 15* here 15 is hour, actually I want to make script in which user just need to add day and time (only in hours no min or seconds)
> #!/bin/bash
read -p " enter the App name : " app
file="/logs/$app/$app.log"
read -p " Enter the Date in this Format --'10 Jan 20 or Jan 10 20' : " first
read -p " Enter the End time of logs : " end
if [ -f "$file" ]
then
if grep -q "$first" "$file"; then
final_first=$first
fi
if grep -q "$end" "$file"; then
final_end=$end
fi
sed -n " /$final_first/,/$final_end/ "p $file >$app.txt
else
echo "$app.log not found, Please check correct log name in deployer"
fi
Sample data:
Apr 07 12:39:15 DEBUG [http-0.0.0.0-8089-21] model.DSSAuthorizationModel - pathInfo : /about-ses
Apr 07 12:39:15 DEBUG [http-0.0.0.0-8089-21] servlet.CasperServlet - Request about to be serviced by model: com.ge.oilandgas.sts.model.SessionValidModel
I'd use a language with built-in datetime parsing or an easily included module. For example, perl
first="Apr 07 12"
end="Apr 08 00"
perl -MTime::Piece -sane '
BEGIN {
$first_ts = Time::Piece->strptime($first, "%b %d %H")->epoch;
$end_ts = Time::Piece->strptime($end, "%b %d %H")->epoch;
}
$ts = Time::Piece->strptime(join(" ", #F[0..2]), "%b %d %T")->epoch;
print if $first_ts <= $ts and $ts <= $end_ts;
' -- -first="$first" -end="$end" <<END
Apr 07 11:39:15 DEBUG [http-0.0.0.0-8089-21] model.DSSAuthorizationModel - pathInfo : /about-ses
Apr 07 12:00:00 DEBUG [http-0.0.0.0-8089-21] model.DSSAuthorizationModel - pathInfo : /about-ses
Apr 07 12:39:15 DEBUG [http-0.0.0.0-8089-21] model.DSSAuthorizationModel - pathInfo : /about-ses
Apr 07 12:39:15 DEBUG [http-0.0.0.0-8089-21] servlet.CasperServlet - Request about to be serviced by model: com.ge.oilandgas.sts.model.SessionValidModel
Apr 07 23:59:59 DEBUG [http-0.0.0.0-8089-21] servlet.CasperServlet - Request about to be serviced by model: com.ge.oilandgas.sts.model.SessionValidModel
Apr 08 00:00:01 DEBUG [http-0.0.0.0-8089-21] servlet.CasperServlet - Request about to be serviced by model: com.ge.oilandgas.sts.model.SessionValidModel
END
outputs
Apr 07 12:00:00 DEBUG [http-0.0.0.0-8089-21] model.DSSAuthorizationModel - pathInfo : /about-ses
Apr 07 12:39:15 DEBUG [http-0.0.0.0-8089-21] model.DSSAuthorizationModel - pathInfo : /about-ses
Apr 07 12:39:15 DEBUG [http-0.0.0.0-8089-21] servlet.CasperServlet - Request about to be serviced by model: com.ge.oilandgas.sts.model.SessionValidModel
Apr 07 23:59:59 DEBUG [http-0.0.0.0-8089-21] servlet.CasperServlet - Request about to be serviced by model: com.ge.oilandgas.sts.model.SessionValidModel
Given your code, I would make the following change:
if ! [ -f "$file" ]; then
echo "$app.log not found, Please check correct log name in deployer"
exit 1
fi
grep -q "$first" "$file" && final_first="/$first/" || final_first='1'
grep -q "$end" "$file" && final_end="/$end/" || final_end='$'
sed -n "${final_first},${final_end}p" "$file" >"$app.txt"
That provides default addresses for the sed range, first line and last line.
Related
I'm fairly new to Linux and trying to learn. I'm using Plex Media Server and I'm trying to prevent the system from sleeping while streaming a file. I've searched the internet over the last few days and none of the solutions seem to work. One solution I feel is almost getting me there, but it's not quite working. Here is the script I've placed (and made executable) in /lib/systemd/system-sleep/ (based on this site).
#!/bin/bash
PATH=/sbin:/usr/sbin:/bin:/usr/bin
X_DISPLAY_USERNAME=myusername
plexresume()
{
number_of_sessions=$(curl -s localhost:32400/status/sessions? | sed -n "s/.*MediaContainer size=\"\(.*\)\".*/\1/p")
if [ ${number_of_sessions} -gt 0 ]; then
echo "[$(date +"%Y.%m.%d-%T")] Number of streamers = ${number_of_sessions} Plex session active, cancel suspend" >> /tmp/plex_sleep_log
return 1
else
echo "[$(date +"%Y.%m.%d-%T")] Number of streamers = ${number_of_sessions} Plex session -IN-active, going to sleep now zzzzzzzz........" >> /tmp/plex_sleep_log
return 0
fi
}
plexkeepalive()
{
echo "[$(date +"%Y.%m.%d-%T")] Resuming!!..." >> /tmp/plex_sleep_log
su ${X_DISPLAY_USERNAME} -c "DISPLAY=:0 /usr/bin/xdotool getmouselocation | grep 'x:1 y:1 '" > /dev/null
if [ "$?" == "0" ]; then
su ${X_DISPLAY_USERNAME} -c "DISPLAY=:0 /usr/bin/xdotool mousemove 9 9"
else
su ${X_DISPLAY_USERNAME} -c "DISPLAY=:0 /usr/bin/xdotool mousemove 1 1"
fi
return 0
}
case "$1" in
pre)
plexresume
;;
post)
plexkeepalive
;;
esac
I know it's executing because it's printing to the log file. But even when it's printing that Plex is active, it's still suspending the system. I've manually run the script using sudo outside of systemd and checking the value of $? after, which is 1.
When I use
journalctl -b -u systemd-suspend.service
I see the following:
Sep 26 12:47:03 systemname systemd[1]: Starting System Suspend...
Sep 26 12:47:03 systemname [141890]: /usr/lib/systemd/system-sleep/plexkeepalive failed with exit status 1.
Sep 26 12:47:03 systemname systemd-sleep[141887]: Entering sleep state 'suspend'...
One time I got a successful result, but I'm not sure how it happened:
Sep 26 10:51:45 systemname systemd-sleep[112491]: Entering sleep state 'suspend'...
Sep 26 10:52:25 systemname systemd-sleep[112491]: Failed to put system to sleep. System resumed again: Device or resource busy
Sep 26 10:52:25 systemname su[112556]: (to myusername) root on none
Sep 26 10:52:25 systemname su[112556]: pam_unix(su:session): session opened for user myusername(uid=1000) by (uid=0)
Sep 26 10:52:25 systemname su[112556]: pam_unix(su:session): session closed for user myusername
Sep 26 10:52:25 systemname su[112592]: (to myusername) root on none
Sep 26 10:52:25 systemname su[112592]: pam_unix(su:session): session opened for user myusername(uid=1000) by (uid=0)
Sep 26 10:52:25 systemname su[112592]: pam_unix(su:session): session closed for user myusername
Sep 26 10:52:25 systemname systemd[1]: systemd-suspend.service: Main process exited, code=exited, status=1/FAILURE
Sep 26 10:52:25 systemname systemd[1]: systemd-suspend.service: Failed with result 'exit-code'.
Sep 26 10:52:25 systemname systemd[1]: Failed to start System Suspend.
Sep 26 10:52:25 systemname systemd[1]: systemd-suspend.service: Consumed 2.732s CPU time.
Any help on this issue would be appreciated. I don't understand why returning 1 from the script is not preventing systemd-suspend.service from running. Thank you!
I'm new with linux
I'm trying to get logs between two dates with gawk.
this is my log
Oct 07 11:00:33 abcd
Oct 08 12:00:33 abcd
Oct 09 14:00:33 abcd
Oct 10 21:00:33 abcd
I can do it when both start and end date are sent
but I have problem when start or end date or both are not sent
and I don't know how to check it .
I've written below code but it has syntax error .
sudo gawk -v year='2022' -v start='' -v end='2022:10:08 21:00:34' '
BEGIN{ gsub(/[:-]/," ", start); gsub(/[:-]/," ", end) }
{ dt=year" "$1" "$2" "$3; gsub(/[:-]/," ", dt) }
if(start && end){mktime(dt)>=mktime(start) && mktime(dt)<=mktime(end)}
else if(end){mktime(dt)<=mktime(end)}
else if(start){mktime(dt)>=mktime(start)} ' log.txt
How can I modify this code ?
I'd write:
gawk -v end="Oct 10 12:00:00" '
function to_epoch(timestamp, n, a) {
n = split(timestamp, a, /[ :]/)
return mktime(strftime("%Y", systime()) " " month[a[1]] " " a[2] " " a[3] " " a[4] " " a[5])
}
BEGIN {
split("Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec", m)
for (i=1; i<=12; i++) month[m[i]]=i
if (start) {_start = to_epoch(start)} else {_start = 0}
if (end) {_end = to_epoch(end)} else {_end = 2**31}
}
{ ts = to_epoch($0) }
_start <= ts && ts <= _end
' log.txt
You'll pass the start and/or end variables with the same datetime format as appears in the log file.
This would be easier with dateutils, e.g.:
<infile dategrep -i '%b %d %H:%M:%S' '>Oct 08 00:00:00' |
dategrep -i '%b %d %H:%M:%S' '<Oct 09 23:59:59'
Output:
Oct 08 12:00:33 abcd
Oct 09 14:00:33 abcd
I have json file named as test.json, I want to parse the value of id, name and not_after then put in condition to verify the not_after should not exceed before 60 days.
vi test.json
{
"id" : 10001,
"name" : "Test Client Name",
"type" : "PKCS12",
"provider" : "SunJSSE",
"password" : "1111111",
"url" : "data:application/xxxx-xxx,1234567890987",
"entry" : [ {
"alias" : "example.com,
"type" : "PrivateKeyEntry",
"algorithm" : "EC",
"subject" : "C=CA, ST=ON, L=Toronto, O=Techonology, OU=example, CN=example.com",
"issuer" : "C=US, O=example Lab, CN=ExampleCA",
"not_before" : "Fri, 21 Aug 2020 19:44:26 GMT",
"not_after" : "Sun, 21 Aug 2022 19:44:26 GMT",
"tn_auth_list" : [ {
"spc" : "AA001"
} ]
} ],
"created_date" : "Thu, 20 Aug 2020 04:38:16 GMT"
}{
"id" : 10002,
"name" : "client-02",
"type" : "PKCS12",
"provider" : "SunJSSE",
"password" : "1111111",
"url" : "data:application/xxxx-xxx,1234567890987",
"customer_id" : 12002,
"entry" : [ {
"alias" : "example.com",
"type" : "PrivateKeyEntry",
"algorithm" : "EC",
"subject" : "C=US, ST=CA, L=San Ramon, O=Five9, OU=example, CN=example.com",
"issuer" : "C=US, O=example Lab, CN=ExampleCA",
"not_before" : "Tue, 2 Jun 2020 12:15:36 GMT",
"not_after" : "Thu, 2 Jun 2022 12:15:36 GMT",
"tn_auth_list" : [ {
"spc" : "ZZ001"
} ]
} ],
"created_date" : "Mon, 14 Dec 2020 21:42:35 GMT"
}
The output of jq could not be consider as one string in while read, so that condition not working properly, If i give only .entry[].not_after I can get the not_after output perfectly. Need some help that while read should not break the names string and it should consider the name as single string.
cat test.json | jq -r '.name, .entry[].not_after' | while read name expirydate; do
echo certname=$name
echo expiryday=$expirydate
not_after="${expirydate}"
echo expirydate=$not_after
condition=$(( $(date +%s) + $((60*24*60*60)) ))
echo condition=$condition
not_after_in_seconds=$(date -d "$not_after" +%s)
# echo not_after_in_seconds: $not_after_in_seconds
# echo not_after_in_date: $(date -d #$not_after_in_seconds)
if [ $condition -ge $not_after_in_seconds ]
then
echo Certificate name : $certname will be expire in 60 days, Expiration Date = $not_after
else
echo No issues for 60 days
fi
done
output:
certname=Test
expiryday=Client Name
expirydate=Client Name
condition=1661241563
date: invalid date 'Client Name'
./dummy.sh: line 15: [: 1661241563: unary operator expected
No issues for 60 days
certname=Sun,
expiryday=21 Aug 2022 19:44:26 GMT
expirydate=21 Aug 2022 19:44:26 GMT
condition=1661241563
Certificate name : will be expire in 60 days, Expiration Date = 21 Aug 2022 19:44:26 GMT
certname=client-02
expiryday=
expirydate=
condition=1661241563
Certificate name : will be expire in 60 days, Expiration Date =
certname=Thu,
expiryday=2 Jun 2022 12:15:36 GMT
expirydate=2 Jun 2022 12:15:36 GMT
condition=1661241563
Certificate name : will be expire in 60 days, Expiration Date = 2 Jun 2022 12:15:36 GMT
Expected output:
Certificate name : Test Client Name will be expire in 60 days, Expiration Date = 21 Aug 2022 19:44:26 GMT
Certificate name : client-02 will be expire in 60 days, Expiration Date = 2 Jun 2022 12:15:36 GMT
We can use | #sh to quote a JSON array for evaluation by the shell:
jq -r '[.name, .entry[].not_after ] | #sh' test.json
Gives:
'Test Client Name' 'Sun, 21 Aug 2022 19:44:26 GMT'
'client-02' 'Thu, 2 Jun 2022 12:15:36 GMT'
Now we have a list of four separate words. We can use eval to store this in a bash array.
An example script:
#!/bin/bash
eval "a=($(jq -r '[.name, .entry[].not_after ] | #sh'))"
for ((i=0; i<${#a[#]}; i+=2)); do
name=${a[i]} expiry=${a[i+1]}
expiry_epoch=$(date -d "$expiry" +%s)
now_epoch=$(date +%s)
days_left=$(( (expiry_epoch - now_epoch) / 86400 ))
if ((days_left == 0)); then
echo "$name: warning: expires today"
elif ((days_left < 0)); then
echo "$name: EXPIRED $((days_left*-1)) days ago"
elif ((days_left < 60)); then
echo "$name: warning: expires in $days_left" days
else
echo "$name: $days_left days left"
fi
done
Use like: expiry-script < test.json
Correctly calculating days remaining isn't always simple. This script truncates the current day (ie. 4.9 days becomes 4 days). That may be desired, but it's also wrong one hour per year, if the timezone has daylight savings time. DST causes a 23 hour day, meaning a day is truncated when it shouldn't be.
One alternative, which doesn't have this problem, is to round up or down to the nearest day:
printf -v days_left %.0f \
"$(echo "scale=1; ($expiry_epoch - $now_epoch)/86400" | bc)"
This is a different approach. Rounding does avoid the DST issue though.
I am working on a script where I want to iterate between the numbers 1 to 15, but want it shown as 01 02 03 ... 13 14 15. Essentially what I am trying to do is add 15 users using the newusers command and using this script as < to the command. newusers needs to be in this format:
pw_name:pw_passwd:pw_uid:pw_gid:pw_gecos:pw_dir:pw_shell
Basically, it should look like this when I run the script with arguments =
cstuser01:EzVlK9Je8JvfQump:1001:1001:CST8177 user:/home/cstuser01:/bin/bash
cstuser02:EsKOfvhgnWpiBT6c:1002:1002:CST8177 user:/home/cstuser02:/bin/bash
cstuser03:qzQuR5vRgxdzY6dq:1003:1003:CST8177 user:/home/cstuser03:/bin/bash
I got most of it working but I am getting the error below:
./15users.sh: 57: ./15users.sh: Illegal number: 08
Here is my script so far (I took out a couple sections with error checking) =
#!/bin/sh -u
PATH=/bin:/usr/bin ; export PATH
umask=022
#num=1 (this variable is needed depending on which loop I use below)
user=$prefix"user"
uid=1001
gid=$uid
home=/home/$user
shell=/bin/bash
#echo "pw_name:pw_passwd:pw_uid:pw_gid:pw_gecos:pw_dir:pw_shell"
#PASSWD=$(openssl rand -base64 12)
I originally had this but ran into a few problems:
while [ $NUM -le 15 ] ; do
if [ $NUM -lt 10 ] ; then
NUM=0$NUM
fi
echo "$USER$NUM:$(openssl rand -base64 12):$UID:$GID:$GECO:$HOME$NUM:$SHELL"
UID=$(( UID + 1 ))
GID=$(( GID + 1 ))
NUM=$(( NUM + 1 ))
done
A friend of mine suggested this, it works perfectly fine. But I am trying to future proof this thing. What if I have a 100 or 1,000 users to add.
for NUM in 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 ; do
echo "$USER$NUM:$(openssl rand -base64 12):$UID:$GID:$GECO:$HOME$NUM:$SHELL"
done
This didn't work:
for num in {01..15} ; do
i=09
echo "$(( 10#$num + 1 ))"
10
done
I then tried this getting a syntax error =
./15users.sh: 50: ./15users.sh: Syntax error: Bad for loop variable
for (( num=1; num<=15; num++ )) ; do
printf "%02d\n" $num
done
I tried this as well but seq prints vertically not horizontally:
#iterate=$(seq -w 1 15)
for $iterate ; do
echo "$user$num:$(openssl rand -base64 12):$uid:$gid:$geco:$home$num:$shell"
done
To loop over 01 to 15, it is much simpler to use brace expansion:
$ for num in {01..15}; do echo "$num"; done
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
In bash, by default, numbers beginning with 0 are octal. Since 08 and 09 are illegal as base-8 numbers, they will cause an error. To avoid that, explicitly specify the base:
$ i=09; echo $(( 10#$i + 1 ))
10
The expression 10#$i tells bash to interpret $i as a base-10 number.
Do NOT use all caps for your script variables. The system uses all caps and you don't want to accidentally overwrite a system variable.
In the case of UID, it is a read-only bash variable. Attempts by your script to assign UID will fail. Use lower or mixed-case for your script variables.
Another example of the all caps problem is $HOME. Note that the following code works:
$ openssl rand -base64 12
1bh9+dp+Ap7xFIBB
But the following fails:
$ (HOME=/home/user; openssl rand -base64 12)
zceZeWsQGpohTPvv
unable to write 'random state'
Apparently, openssl expects to have write-access to $HOME.
Assigning HOME to a non-existent directory causes an error.
So, again, do not all all caps for your script variables.
I won't try to diagnose your error message, but you're over-complicating what you're trying to achieve.
for i in {01..15}; do echo $i; done
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
Bash supports C style loops as well:
$ for (( i=1; i<=15; i++ )); do printf "%02d\n" $i; done
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
Just use printf with the flag to print leading 0 and you have your output.
Since it hasn't been mentioned yet:
seq -w 1 15
seq -w 1 15 | while read num; do echo "n=$num"; done
I have a log directory that consists of bunch of log files, one log file is created once an system event has happened. I want to write an oneline bash script that always monitors the file list and display the content of the newly created file on the terminal. Here is what it looks like:
Currently, all I have is to display the content of the whole directory:
for f in *; do cat $f; done
It lacks the monitoring feature that I wanted. One limitation of my system is that I do not have watch command. I also don't have any package manager to install fancy tools. Raw BSD is all I have. I do have tail, I was thinking of something like tail -F $(ls) but this tails each file instead of the file list.
In summary, I want to modify my script such that I can monitor the content of all newly created files.
First approach - use a hidden file in you dir (in my example it has a name .watch). Then you one-liner might look like:
for f in $(find . -type f -newer .watch); do cat $f; done; touch .watch
Second approach - use inotify-tools: https://unix.stackexchange.com/questions/273556/when-a-particular-file-arrives-then-execute-a-procedure-using-shell-script/273563#273563
You can cram it into a one-liner if you want, but I'd recommend just running the script in the background:
#!/bin/bash
[ ! -d "$1" ] && {
printf "error: argument is not a valid directory to monitory.\n"
exit 1
}
while :; fname="$1/$(inotifywait -q -e modify -e create --format '%f' "$1")"; do
cat "$fname"
done
Which will watch the directory given as the first argument, and cat any new or changed file in that directory. Example:
$ bash watchdir.sh my_logdir &
Which will then cat new or changed files in my_logdir.
Using inotifywait in monitor mode
First this little demo:
Open one terminal and run this:
ext=(php css other)
while :;do
subname=''
((RANDOM%10))||printf -v subname -- "-%04x" $RANDOM
date >/tmp/test$subname.${ext[RANDOM%3]}
sleep 1
done
This will create randomly files named /tmp/test.php, /tmp/test.css and /tmp/test.other, but randomly (approx 1 time / 10), the name will be /tmp/test-XXXX.[css|php|other] where XXXX is an hexadecimal random number.
Open another terminal and run this:
waitPaths=(/{home,tmp})
while read file ;do
if [ "$file" ] &&
( [ -z "${file##*.php}" ] || [ -z "${file##*.css}" ] ) ;then
(($(stat -c %Y-%X $file)))||echo -n new
echo file: $file, content:
cat $file
fi
done < <(
inotifywait -qme close_write --format %w%f ${waitPaths[*]}
)
This may produce something like:
file: /tmp/test.css, content:
Tue Apr 26 18:53:19 CEST 2016
file: /tmp/test.php, content:
Tue Apr 26 18:53:21 CEST 2016
file: /tmp/test.php, content:
Tue Apr 26 18:53:23 CEST 2016
file: /tmp/test.css, content:
Tue Apr 26 18:53:25 CEST 2016
file: /tmp/test.php, content:
Tue Apr 26 18:53:27 CEST 2016
newfile: /tmp/test-420b.php, content:
Tue Apr 26 18:53:28 CEST 2016
file: /tmp/test.php, content:
Tue Apr 26 18:53:29 CEST 2016
file: /tmp/test.php, content:
Tue Apr 26 18:53:30 CEST 2016
file: /tmp/test.php, content:
Tue Apr 26 18:53:31 CEST 2016
Some explanation:
waitPaths=(/{home,tmp}) could be written waitPaths=(/home /tmp) or for only one directory: waitPaths=/var/log
if condition search for filenames matching *.php or *.css
(($(stat -c %Y-%X $file)))||echo -n new will compare creation and modification time.
inotifywait
-q to stay quiet (don't print more then required)
-m for monitor mode: Command don't termine, but print each matching event.
-e close_write react only to specified kind of event.
-f %w%f Output format: path/file
Another way:
There is a more sophisticated sample:
Listenning for two kind of events (CLOSE_WRITE | CREATE)
Using a list of new files flags for knowing which files are new when CLOSE_WRITE event occur.
In second console, hit Ctrl+C, or in new terminal, tris this:
waitPaths=(/{home,tmp})
declare -A newFiles
while read path event file; do
if [ "$file" ] && ( [ -z "${file##*.php}" ] || [ -z "${file##*.css}" ] ); then
if [ "$event" ] && [ -z "${event//*CREATE*}" ]; then
newFiles[$file]=1
else
if [ "${newFiles[$file]}" ]; then
unset newFiles[$file]
echo NewFile: $file, content:
sed 's/^/>+ /' $file
else
echo file: $file, content:
sed 's/^/> /' $path/$file
fi
fi
fi
done < <(inotifywait -qme close_write -e create ${waitPaths[*]})
May produce something like:
file: test.css, content:
> Tue Apr 26 22:16:02 CEST 2016
file: test.php, content:
> Tue Apr 26 22:16:03 CEST 2016
NewFile: test-349b.css, content:
>+ Tue Apr 26 22:16:05 CEST 2016
file: test.css, content:
> Tue Apr 26 22:16:08 CEST 2016
file: test.css, content:
> Tue Apr 26 22:16:10 CEST 2016
file: test.css, content:
> Tue Apr 26 22:16:13 CEST 2016
Watching for new files AND new lines in old files, using bash
There is another solution by using some bashisms like associative arrays:
Sample:
wpath=/var/log
while : ;do
while read -a crtfile ;do
if [ "${crtfile:0:1}" = "-" ] &&
[ "${crtfile[8]##*.}" != "gz" ] &&
[ "${files[${crtfile[8]}]:-0}" -lt ${crtfile[4]} ] ;then
printf "\e[47m## %-14s :- %(%a %d %b %y %T)T ##\e[0m\n" ${crtfile[8]} -1
tail -c +$[1+${files[${crtfile[8]}]:-0}] $wpath/${crtfile[8]}
files[${crtfile[8]}]=${crtfile[4]}
fi
done < <( /bin/ls -l $wpath )
sleep 1
done
This will dump each files (with filename not ending by .gz) in /var/log, and watch for modification or new files, then dump new lines.
Demo:
In a first terminal console, hit:
ext=(php css other)
( while :; do
subname=''
((RANDOM%10)) || printf -v subname -- "-%04x" $RANDOM
name=test$subname.${ext[RANDOM%3]}
printf "%-16s" $name
{
date +"%a %d %b %y %T" | tee /dev/fd/5
fortune /usr/share/games/fortunes/bofh-excuses
} >> /tmp/$name
sleep 1
done ) 5>&1
You need to have fortune installed with BOFH excuses librarie.
If you really not have fortune, you could use this instead:
LANG=C ext=(php css other)
( while :; do
subname=''
((RANDOM%10)) || printf -v subname -- "-%04x" $RANDOM
name=test$subname.${ext[RANDOM%3]}
printf "%-16s" $name
{
date +"%a %d %b %y %T" | tee /dev/fd/5
for ((1; RANDOM%5; 1))
do
printf -v str %$[RANDOM&12]s
str=${str// /blah, }
echo ${str%, }.
done
} >> /tmp/$name
sleep 1
done ) 5>&1
This may output something like:
test.css Thu 28 Apr 16 12:00:02
test.php Thu 28 Apr 16 12:00:03
test.other Thu 28 Apr 16 12:00:04
test.css Thu 28 Apr 16 12:00:05
test.css Thu 28 Apr 16 12:00:06
test.other Thu 28 Apr 16 12:00:07
test.php Thu 28 Apr 16 12:00:08
test.css Thu 28 Apr 16 12:00:09
test.other Thu 28 Apr 16 12:00:10
test.other Thu 28 Apr 16 12:00:11
test.php Thu 28 Apr 16 12:00:12
test.other Thu 28 Apr 16 12:00:13
In a second terminal console, hit:
declare -A files
wpath=/tmp
while :; do
while read -a crtfile; do
if [ "${crtfile:0:1}" = "-" ] && [ "${crtfile[8]:0:4}" = "test" ] &&
( [ "${crtfile[8]##*.}" = "css" ] || [ "${crtfile[8]##*.}" = "php" ] ) &&
[ "${files[${crtfile[8]}]:-0}" -lt ${crtfile[4]} ]; then
printf "\e[47m## %-14s :- %(%a %d %b %y %T)T ##\e[0m\n" ${crtfile[8]} -1
tail -c +$[1+${files[${crtfile[8]}]:-0}] $wpath/${crtfile[8]}
files[${crtfile[8]}]=${crtfile[4]}
fi
done < <(/bin/ls -l $wpath)
sleep 1
done
This will each seconds
for all entries in watched directory
search for files (first caracter is -),
search for filenames begining by test,
search for filenames ending by css or php,
compare already printed sizes with new file size,
if new size greater,
print out new bytes by using tail -c and
store new already printed size
sleep 1 seconds
this may output something like:
## test.css :- Thu 28 Apr 16 12:00:09 ##
Thu 28 Apr 16 12:00:02
BOFH excuse #216:
What office are you in? Oh, that one. Did you know that your building was built over the universities first nuclear research site? And wow, aren't you the lucky one, your office is right over where the core is buried!
Thu 28 Apr 16 12:00:05
BOFH excuse #145:
Flat tire on station wagon with tapes. ("Never underestimate the bandwidth of a station wagon full of tapes hurling down the highway" Andrew S. Tannenbaum)
Thu 28 Apr 16 12:00:06
BOFH excuse #301:
appears to be a Slow/Narrow SCSI-0 Interface problem
## test.php :- Thu 28 Apr 16 12:00:09 ##
Thu 28 Apr 16 12:00:03
BOFH excuse #36:
dynamic software linking table corrupted
Thu 28 Apr 16 12:00:08
BOFH excuse #367:
Webmasters kidnapped by evil cult.
## test.css :- Thu 28 Apr 16 12:00:10 ##
Thu 28 Apr 16 12:00:09
BOFH excuse #25:
Decreasing electron flux
## test.php :- Thu 28 Apr 16 12:00:13 ##
Thu 28 Apr 16 12:00:12
BOFH excuse #3:
electromagnetic radiation from satellite debris
Nota: If some file are modified more than one time between two checks, all modification will be printed on next check.
Although not really nice, the following gives (and repeats) the last 50 lines of the newest file in the current directory:
while true; do tail -n 50 $(ls -Art | tail -n 1); sleep 5; done
You can refresh every minute using a cronjob:
$crontabe -e
* * * * * /home/script.sh
if you need to refresh in less than a minute you can use the command "sleep" inside your script.