0

I made a small Bash-script to make my life easier. But I encountered a problem which I can't fix.

What I want
I've made a small script which will check for php-errors in a file each time that file gets saved/changed. This is done without me needing to run a command each time. So I run the Bash-script once on my second screen, and than each time when I save my PHP-file on screen one; I get the eventual errors shown on screen two automatically.

Basic algorithm

  1. Get the hash of the file
  2. Compare it to it's previous hash
  3. If it differs, the file is changed/saved: Check if there are errors using the php -l command
  4. Print out the result from php -l

Problem: The result from php -l gets printed out before my code asked for it.

Code

#!/bin/bash

#Declaring basic variables here
fileToCheck="$1"

oldHash=("")
checksum=("")

#Function to get a striped line as long as the terminal width
function lineAmount {
    cwidth=`tput cols`
    lines=""
    for i in $(seq $(expr $cwidth - 33)); do lines="$lines-";done
    echo $lines
}


#Function to show the actual error
function showError {
    msg=$1
    time=`date +"%c"`
    l=$(lineAmount)

    if [ "$msg" == "No" ]
        then
            msg="No errors detected."
    fi

    printf "\n\n$time $l \n$msg\n"
}

#Start-screen------------------------------------------------
printf "Starting session for $1 at $time \n$(lineAmount)\n"
if [ ! -f $1 ]
    then
        echo "[Error] File $1 not found."
        exit
fi
printf "\n\n\n"
#------------------------------------------

#Printing out error when file changed
while true
    do
        sleep 0.6 
        checksum=($(sha256sum $fileToCheck))
        checksum=${checksum[0]}

        if [ "$checksum" != "$oldHash" ]
            then
                error=$(php -l $fileToCheck)
                oldHash=$checksum

                showError $error
        fi
done

Test file (test.php):

<?php
    function foo() {

    }
?>

Output of script:

Starting session for /home/name/Desktop/test.php at  
-----------------------------------------------





Thu 11 Aug 2016 08:16:15 PM CEST ----------------------------------------------- 
No errors detected.

Now, in test.php I delete line 4:

<?php
    function foo() {


?>

This will of course give an error, and my script shows that error:

Starting session for /home/name/Desktop/test.php at  
-----------------------------------------------





Thu 11 Aug 2016 08:16:15 PM CEST ----------------------------------------------- 
No errors detected.
PHP Parse error:  syntax error, unexpected end of file in /home/name/Desktop/test.php on line 6


Thu 11 Aug 2016 08:19:37 PM CEST ---------------------------------------------------------------------------------- 
Parse

But like you can see, this is not a nice output. PHP Parse error: syntax error, unexpected end of file in /home/name/Desktop/test.php on line 6 should be printed below the second dotted line. Not below "No errors found." (The first output).

Expected output:

Starting session for /home/name/Desktop/test.php at  
-----------------------------------------------





Thu 11 Aug 2016 08:16:15 PM CEST ----------------------------------------------- 
No errors detected.


Thu 11 Aug 2016 08:19:37 PM CEST ---------------------------------------------------------------------------------- 
PHP Parse error:  syntax error, unexpected end of file in /home/name/Desktop/test.php on line 6

I tried a lot, I tried to change my algorithm a bit, searched up a lot; but it ain't working. I guess the problem is somewhere on line 51, or 29. But I really can't see what's wrong.

Thanks!

O'Niel
  • 1,622
  • 1
  • 17
  • 35
  • How are you editing the php file? Is your editor auto-saving for you perhaps? – Eric Renouf Aug 11 '16 at 18:31
  • @EricRenouf I'm using Vim, and I'm saving with the :w function. No auto-save function as far as I know. I also tried it with the default Text Editor on Linux Mint and got the same result. – O'Niel Aug 11 '16 at 18:50

1 Answers1

4

Here's a stripped down and simplified version of your problem:

Why does this print an error message immediately instead of assigning it to the variable?

$ error=$(php -l test.php)
PHP Parse error:  syntax error, unexpected end of file in test.php on line 5

php -l prints error messages to stderr like a good Unix citizen should. $(..) only captures stdout.

If you want to capture stdout and stderr together, you can use:

error=$(php -l $fileToCheck 2>&1)

You should also quote your variables so that the message is passed as a single parameter, since you're currently throwing away most of it (shellcheck is helpful):

showError "$error"

Being a good citizen, php also returns a useful exit code, so instead of trying to match a "No" to see if it's successful, you can just check the status directly:

if error=$(php -l $fileToCheck 2>&1)
then
  echo "No problems"
else
  echo "It failed with these messages: $error"
fi
that other guy
  • 116,971
  • 11
  • 170
  • 194