I use linux command line and I'm a beginner with it. I've created two files, test.sh and test.log. the process is any output going to test.log and i get it successfully the output in test.log. I want to run a script automatically every 5 seconds and write only if there is any change with the .sh file.

test.sh contains :

while [ true ] ;
echo "" date and Time >> test.log
date +%x_r >> test.log
lsusb >> test.log

sleep 5;

My question: Is there any way to run it automatically and only append the new change in the file with the new date? for example if anyone insert USB device into my machine it will append it with the new date into the existing log file it.

  • This seems like an unnecessarily complicated way to do it. You should check the manpages for cron – Simme Nov 16 '16 at 17:25

This should work, it stores the last output of lsusb in $lastoutput and appends if they're if not equal

while [ true ] 
    if [ "$currentoutput" != "$lastoutput" ]
        echo "" date and Time >> test.log
        date +%x_r >> test.log
        lsusb >> test.log
    sleep 5
  • Thanks , but in this way it will not save the new change in .log file ,, i try it and it's running in the terminal not in the .log file – Ghassan Nov 16 '16 at 18:29
  • Yes its in the terminal , but the result (new change) should go to .log file but does not . – Ghassan Nov 16 '16 at 20:55
  • @Ghassan does the user running the script have enough permissions to write in the test.log file? Could it be that maybe you created the file as root and is now running it as your regular user? – IanC Nov 16 '16 at 23:49
  • My apologies, I did not realize that the code doesn't work (I was typing on my phone and I wasn't able to test it). I fixed it now, it should work – Evan Chen Nov 16 '16 at 23:54
  • 1
    This runs lsusb twice, potentially with different output. The proper way to do this is probably lastoutput=$(lsusb | tee -a test.log) to assign the variable and append to the log file in one go. – tripleee Apr 12 at 5:05

Instead of always logging the whole output of lsusb, you could use diff to output the changes only.



while sleep 1; do
    diff=$(diff <(printf '%s\n' "$lsusbout_before") <(printf '%s\n' "$lsusbout_now"))
    if [ $? = 1 ]; then
        date | tee -a "$logfile"
        printf '%s\n' "$diff" | grep '^[<>]' | tee -a "$logfile"

Whenever something is added, diff outputs:

> ...

if something is removed, the output is

< ...

e.g. when I attach my USB stick:

Fr 12. Apr 10:55:48 CEST 2019
> Bus 002 Device 014: ID 8564:1000 Transcend Information, Inc. JetFlash

This script makes use of diff error code 1 if the files differ.

  • <(command) file descriptor: generates a file in memory with the output of command as input, similar to $(command).
  • [ $? = 1 ] check error code of last command (here: diff).
  • grep '^[<>]' is to suppress additional output of diff like position of changes which is irrelevant for us.

You have to:

  • put your file in /etc/init.d directory
  • make your sh file executable (use the chmod +x command)

If it doesn't work properly, create a symlink of your file to /etc/rc.d/:

ln -s /etc/init.d/test.sh /etc/rc.d/ 

May that helps :)

  • The question asks how to automatically detect change, not how to start on boot – Evan Chen Nov 16 '16 at 18:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.