Home > OS >  Process two commands into variables simultaneously
Process two commands into variables simultaneously

Time:09-05

I made this motd script:

#!/bin/bash

# Calulate avg CPU usage
usage=$((100-$(vmstat 1 2|tail -1|awk '{print $15}')))
aptlist=$(apt list --upgradable 2> /dev/null | sed 1d)

# Check if current usage isn't to high, else don't display the motd
if [[ ${usage%.*} -ge 95 ]];
then
  printf "motd disabled because current usage is %s\n" "$usage"
else
  # The magic
  date=$(date)
#  usage=$(tail /proc/loadavg | awk '{print $1}')
  root_usage=$(df -h / | awk '/\// {print $(NF-1)}')
#  memory_usage=$(free -m | grep Mem | awk '{print 100/$2*($2-$6 $5)}' | xargs printf "$1""%.2f")
  memory_usage=$(printf "%0.2f MB %d%%\n" $(( $(sed -E '/^(MemTotal|MemFree|Cached|Buffers): *([0-9]*).*/'\
'{s//\2/;H;};$!d;x;s/[[:cntrl:]]//;s__/1024-_g;s_$_/1024_' /proc/meminfo) )) \
$(( $(sed -E '/^(MemTotal|MemFree|Cached|Buffers): *([0-9]*).*/'\
'{s//\2/;H;};$!d;x;s/[[:cntrl:]]//;s_([^\n] )\n_@\1@100*(\1/1024-(_;s_\n_/1024 _g;'\
's_@([^@] )@(.*)$_\2/1024))/(\1/1024)_' /proc/meminfo) )) | awk '{print $3}')
  users=$(users | wc -w)
  time=$(uptime | grep -ohe 'up .*' | sed 's/,/\ hours/g' | awk '{ printf $2" "$3 }')
  processes=$(ps aux | wc -l)
  ip=$(ip addr | awk '/inet / { print $2 }' | sed -n '2{p;q}' | cut -d '/' -f1)
  ipv6=$(ip -6 addr |awk '{print $2}'| grep -v "^::" | grep "/" | head -n1 | cut -d '/' -f1)
  packages=$(dpkg-query -l | grep -c "^ii")
  updates=$(echo -n $aptlist | wc -l )
  secupdates=$(echo $aptlist | grep -c security )

  # The updates and secupdates var get's it's info thanks to this crontab/command
  # sudo apt-get -s dist-upgrade | grep "^Inst" | wc -l > /etc/update-motd.d/pkg.stats && apt-get -s dist-upgrade | grep "^Inst" | grep -i security | wc -l >> /etc/update-motd.d/pkg.stats
  # sudo crontab -l | { cat; echo "0 0 * * * apt-get -s dist-upgrade | grep "^Inst" | wc -l > /etc/update-motd.d/pkg.stats && apt-get -s dist-upgrade | grep "^Inst" | grep -i security | wc -l >> /etc/update-motd.d/pkg.stats"; } | crontab -
  # If you wish to not use crontab, switch the updates and secupdates comment's.

  # Header & motd
  printf "Welcome to %s (%s)" "$(lsb_release -s -d)" "$(uname -rm)"
  printf "\n"

  echo "     __ __  __ _  __            _______"
  echo "    / //_/ / /(_)/ /__ ____    \|_____|"
  echo "   / ,<   / // // //_// __ \    | │ │ |"
  echo "  / /| | / // // ,<  / /_/ /    |     |"
  echo " /_/ |_|/_//_//_/|_| \____/     ◯_____| "
  echo

  # System information
  echo "System information as of: $date"
  echo
#  printf "System Load:\t%s\tSystem Uptime:\t%s\n" "$load" "$time" # Use this one if you prefer the linux proc avg
  printf "System Load:\t%s%%\tSystem Uptime:\t%s\n" "$usage" "$time"  # Overall processor usage
  printf "Memory Usage:\t%s\tIP Address:\t%s\n" "$memory_usage" "$ip"
  if [[ $ipv6 == "" ]]
  then
    printf "Usage On /:\t%s\tIPv6 Addres:\tNo ipv6 address found\n" "$root_usage"
  else
    printf "Usage On /:\t%s\tIPv6 Addres:\t%s\n" "$root_usage" "$ipv6"
  fi
  printf "Local Users:\t%s\tProcesses:\t%s\n" "$users" "$processes"
  printf "Packages dpkg:\t%s\tSession fortune:\ \n\n" "$packages"

  /usr/games/fortune

  # Check if there are updates
  echo
  if [[ $updates != 0 ]]
  then
    printf "%s updates can be installed immediately.\n" "$updates"
    printf "%s of these updates are security updates.\n" "$secupdates"
    printf "To see these additional updates run: apt list --upgradable\n\n"
  else
    printf "System is up-to-date!\n\n"
  fi

  # Check if a reboot is needed
  if [[ -f /var/run/reboot-required ]]
  then
    echo '*** System restart required ***'
  fi
fi
printf "%s" "$aptlist"

Now the execution time is 2 seconds b/c of these two commands:

usage=$((100-$(vmstat 1 2|tail -1|awk '{print $15}')))
aptlist=$(apt list --upgradable 2> /dev/null | sed 1d)

I tried to find a way to run both of the commands at the same time, so that it only takes a second (which would be amazing). Sadly using var1=cmd1 & var2=cmd2 doesn't work and only the second get's executed properly.

Anyone has a clue how to run two commands that go into each of their variables at the same time? (i prefer to use the default tools in debian/Raspberry but if it's impossible, i'm ok to install that package :))

Thank you for reading!

CodePudding user response:

One approach:

  • kick the 2x time consuming commands off in the background, making sure to redirect stdout/stderr to a pair of temp files
  • wait
  • process the 2x temp files and populate the 2x variables

For example:

(vmstat 1 2 | tail -1 | awk '{print $15}'    > tmp.1 2>&1) &
(apt list --upgradable 2> /dev/null | sed 1d > tmp.2 2>&1) &

wait

usage=$((100 - $(cat tmp.1)))
read -r aptlist < tmp.2

NOTE: OP could add any necessary error checking after the wait and before the usage=$((...)); read -r aptlist ... commands

CodePudding user response:

use a dummy single-cycle for loop as a proxy for waiting :

 fgc; a0000=''; b0000=''; gdcmd='%n%n %D %T %s.%-N %n%n'

 gdate  "${gdcmd}"

 ( time ( for idx in 1; do {

       a0000=` lsof &` 
       b0000="$( df -h | mawk 'END { print }' & )" 
 } done
 
 echo "${b0000}\n"

 printf '%s' "${a0000}" | wc5 ) )
 gdate  "${gdcmd}";


  09/04/22 16:24:30 1662323070.513516 


 //guest:@192.168.1.3/WD_4TB_RAID1/55_MyCloud_12T   
 11Ti   11Ti    0Bi   100% 11625431486 0  100% /Volumes/55_MyCloud_12T


  rows = 7330. | UTF8 chars = 1153070. | bytes      = 1153312.

 
 ( for idx in 1; do; { a0000=` lsof &` ; b0000= ; }; done; echo "${b0000}\n"; )
 0.03s user 0.03s system 46% cpu 0.125 total


 09/04/22 16:24:30 1662323070.642752 

As for ur commands, u can streamline them into

vmstat 1 2 | mawk 'END { print 100 - $15 }'

and

apt list --upgradable 2>/dev/null | mawk '_{ exit }--_'
  • Related