Can someone help me to get this script to work?

About writing shell scripts and making the most of your shell
Forum rules
Topics in this forum are automatically closed 6 months after creation.
Locked
chris888c

Can someone help me to get this script to work?

Post by chris888c »

I am trying to get the following script to work; it outputs CPU utilisation and temp.

https://askubuntu.com/questions/1173520 ... -every-sec

Code: Select all

#!/bin/bash

# by Paul Colby (http://colby.id.au), no rights reserved ;)

# Temperature inputs.
TEMP_INPUT=$(echo /sys/class/hwmon/hwmon1/{temp1_input,temp2_input,temp3_input})

PREV_TOTAL=0
PREV_IDLE=0

while true; do
  # Get the total CPU statistics, discarding the 'cpu ' prefix.
  CPU=(`sed -n 's/^cpu\s//p' /proc/stat`)
  IDLE=${CPU[3]} # Just the idle CPU time.

  # Calculate the total CPU time.
  TOTAL=0
  for VALUE in "${CPU[@]}"; do
    let "TOTAL=$TOTAL+$VALUE"
  done

  # Calculate the CPU usage since we last checked.
  let "DIFF_IDLE=$IDLE-$PREV_IDLE"
  let "DIFF_TOTAL=$TOTAL-$PREV_TOTAL"
  let "DIFF_USAGE=(1000*($DIFF_TOTAL-$DIFF_IDLE)/$DIFF_TOTAL+5)/10"

  # Calculate highest CPU Temperature.
  HIGH_TEMP=$(echo "scale=1; $(sort -r $TEMP_INPUT | head -n1) / 1000" | bc)

  # Redirect CPU temperature and % of CPU usage to file.
  echo "$(date '+%H:%M:%S'): +${HIGH_TEMP}°C ${DIFF_USAGE}%" >> cpu.txt

  # Remember the total and idle CPU times for the next check.
  PREV_TOTAL="$TOTAL"
  PREV_IDLE="$IDLE"

  # Wait before checking again.
  sleep 1
done
When I run it via 'sh ./scriptfilename.sh' I get the error message '... Syntax error: "(" unexpected (expecting "done")

I understand that its an open Parentheses that is confusing it, and it seems to be getting to the end of the file before it realizes this; I just dont know how to fix it!

Thanks for any advice on helping me to get this to work.
Last edited by LockBot on Wed Dec 28, 2022 7:16 am, edited 1 time in total.
Reason: Topic automatically closed 6 months after creation. New replies are no longer allowed.
chris888c

Re: Can someone help me to get this script to work?

Post by chris888c »

Sorry. Thanks for moving this into the correct category.
User avatar
xenopeek
Level 25
Level 25
Posts: 29460
Joined: Wed Jul 06, 2011 3:58 am

Re: Can someone help me to get this script to work?

Post by xenopeek »

chris888c wrote: Sun Feb 21, 2021 3:27 am When I run it via 'sh ./scriptfilename.sh' I get the error message '... Syntax error: "(" unexpected (expecting "done")
I think that's the explanation. It's not a sh (dash) script but a bash script. Invoke it properly. Either mark the file executable (chmod +x filename) and then invoke it as ./scriptfilename.sh (which from the hashbang line automatically invokes bash) or manually run it with bash bash scriptfilename.sh. It works fine here.
Image
chris888c

Re: Can someone help me to get this script to work?

Post by chris888c »

Thanks. I am still a complete newbie, I don't really understand what bash is, or how it would connect to the first line comment eg #!/bin/bash

I have quite a lot of experience of coding on Windows (C/C++) and for Web development (PHP, SQL, and some Python), but my understanding of scripting and how Linux works is very limited.

I chmod the file and ran it how you suggested, it works but all I get is just a flashing cursor with no output?

I also tried running it as a bash command, but got the same flashing cursor with no output.

So I tried instead to run just the CPU temp command/script which worked fine:

Code: Select all

echo "scale=1; $(sort -nr /sys/class/hwmon/hwmon1/{temp1_input,temp2_input,temp3_input} | head -n1) / 1000" | bc
I also tried running just the Github script that displays just the CPU utilisation part, and that worked fine:

Code: Select all

#!/bin/bash
# by Paul Colby (http://colby.id.au), no rights reserved ;)
 
PREV_TOTAL=0
PREV_IDLE=0
 
while true; do
  # Get the total CPU statistics, discarding the 'cpu ' prefix.
  CPU=($(sed -n 's/^cpu\s//p' /proc/stat))
  IDLE=${CPU[3]} # Just the idle CPU time.
 
  # Calculate the total CPU time.
  TOTAL=0
  for VALUE in "${CPU[@]:0:8}"; do
    TOTAL=$((TOTAL+VALUE))
  done
 
  # Calculate the CPU usage since we last checked.
  DIFF_IDLE=$((IDLE-PREV_IDLE))
  DIFF_TOTAL=$((TOTAL-PREV_TOTAL))
  DIFF_USAGE=$(((1000*(DIFF_TOTAL-DIFF_IDLE)/DIFF_TOTAL+5)/10))
  echo -en "\rCPU: $DIFF_USAGE%  \b\b"
 
  # Remember the total and idle CPU times for the next check.
  PREV_TOTAL="$TOTAL"
  PREV_IDLE="$IDLE"
 
  # Wait before checking again.
  sleep 1
done
So I am not sure why the code that brings both of these 2 scripts together just produces a flashing cursor?

Code: Select all

#!/bin/bash

# by Paul Colby (http://colby.id.au), no rights reserved ;)

# Temperature inputs.
TEMP_INPUT=$(echo /sys/class/hwmon/hwmon1/{temp1_input,temp2_input,temp3_input})

PREV_TOTAL=0
PREV_IDLE=0

while true; do
  # Get the total CPU statistics, discarding the 'cpu ' prefix.
  CPU=(`sed -n 's/^cpu\s//p' /proc/stat`)
  IDLE=${CPU[3]} # Just the idle CPU time.

  # Calculate the total CPU time.
  TOTAL=0
  for VALUE in "${CPU[@]}"; do
    let "TOTAL=$TOTAL+$VALUE"
  done

  # Calculate the CPU usage since we last checked.
  let "DIFF_IDLE=$IDLE-$PREV_IDLE"
  let "DIFF_TOTAL=$TOTAL-$PREV_TOTAL"
  let "DIFF_USAGE=(1000*($DIFF_TOTAL-$DIFF_IDLE)/$DIFF_TOTAL+5)/10"

  # Calculate highest CPU Temperature.
  HIGH_TEMP=$(echo "scale=1; $(sort -r $TEMP_INPUT | head -n1) / 1000" | bc)

  # Redirect CPU temperature and % of CPU usage to file.
  echo "$(date '+%H:%M:%S'): +${HIGH_TEMP}°C ${DIFF_USAGE}%" >> cpu.txt

  # Remember the total and idle CPU times for the next check.
  PREV_TOTAL="$TOTAL"
  PREV_IDLE="$IDLE"

  # Wait before checking again.
  sleep 1
done
User avatar
xenopeek
Level 25
Level 25
Posts: 29460
Joined: Wed Jul 06, 2011 3:58 am

Re: Can someone help me to get this script to work?

Post by xenopeek »

chris888c wrote: Sun Feb 21, 2021 5:41 am I don't really understand what bash is, or how it would connect to the first line comment eg #!/bin/bash
https://en.wikipedia.org/wiki/Bash_(Unix_shell)
https://en.wikipedia.org/wiki/Shebang_(Unix)
chris888c wrote: Sun Feb 21, 2021 5:41 am So I am not sure why the code that brings both of these 2 scripts together just produces a flashing cursor?
If you don't know bash do at least read the comments in the code :)

Code: Select all

  # Redirect CPU temperature and % of CPU usage to file.
  echo "$(date '+%H:%M:%S'): +${HIGH_TEMP}°C ${DIFF_USAGE}%" >> cpu.txt
Check the directory where you have the script, there should be a cpu.txt file that gets updated every second while the script is running.

If you don't want the output in a file, remove the output redirect >> cpu.txt from the echo command.
Image
chris888c

Re: Can someone help me to get this script to work?

Post by chris888c »

I just worked it out by looking through the code. It actually writes everything out to a text file!

The code works fine; thanks again for your help
chris888c

Re: Can someone help me to get this script to work?

Post by chris888c »

I must have posted just seconds after you did lol.
User avatar
Termy
Level 12
Level 12
Posts: 4254
Joined: Mon Sep 04, 2017 8:49 pm
Location: UK
Contact:

Re: Can someone help me to get this script to work?

Post by Termy »

You might find this tool interesting, as it just makes use of SYSFS. It's written in Perl, but the main part (line 45+) is quite straight-forward. I used to have a Shell version, but I dunno where it is. :roll:

Just wrote an efficient Bourne Shell approach to this which you might find interesting:

Code: Select all

#!/bin/sh

CPU=0
File='/proc/cpuinfo'
if [ -f "$File" -a -r "$File" ]; then
    while IFS=':' read Key Value; do
        case $Key in
            cpu\ MHz*)
                CPU=$((CPU + 1))
                printf '%d: %.0f\n' $CPU $Value ;;
        esac
    done < "$File"
else
    printf "ERROR: File '%s' missing or unreadable.\n" 1>&2
    exit 1
fi
Here's the above, with comments:

Code: Select all

#!/bin/sh

# We're counting the number of 'CPUs' (cores, basically).
# This code likely won't be suitable for multi-CPU systems.
CPU=0

# If file exists and is readable, then continue, else error out.
File='/proc/cpuinfo'
if [ -f "$File" -a -r "$File" ]; then
    # Read each line from the file -- one at a time. Using an IFS
    # (Input Field Separator) of a colon (':'). Using the `read`
    # builtin, where Key is assigned everything before the colon, -
    # and Value is everything thereafter, including spaces.
    while IFS=':' read Key Value; do
        # Using a case statement for the glob pattern matching.
        case $Key in
            cpu\ MHz*)
                # Incrementing the CPU variable's integer, using
                # arithmetic expansion.
                CPU=$((CPU + 1))
                
                # Displaying the CPU count as an integer, and the
                # float of the current core frequency as an integer.
                printf '%d: %.0f\n' $CPU $Value ;;
        esac
    done < "$File"
else
    # Displaying an error, redirecting its output to STDERR.
    printf "ERROR: File '%s' missing or unreadable.\n" 1>&2
    
    # Leaving script with non-zero exit status, indicating an error.
    exit 1
fi
A lot of this stuff is documented in the BASH manual, so be sure to check that out, via: man bash
I'm also Terminalforlife on GitHub.
Locked

Return to “Scripts & Bash”