1

I'm running into an issue where my script will only set the integer that I need for the variable $alive if I allow the following error to show. uptime: /dev/ttys001: No such file or directory

I've attempted to remove this by adding &>/dev/null either behind uptime or behind the command in this context below,

(( uptime | grep -ohe 'up .*' | sed 's/,//g' | awk '{ print $2 }')&>/dev/null)

or

( uptime &>/dev/null | grep -ohe 'up .*' | sed 's/,//g' | awk '{ print $2 }')

but this causes the following to happen

This computer has been awake for  days

whereas I need it to set the variable and perform like so

This computer has been awake for 32 days

This is more of a personal project for me to understand scripting using bash within MacOS so any additional insight is greatly appreciated!

Here is the script in its context. It is intended to be an infinite loop to keep the computer on for remote access at all times and can be stopped by simply terminating the running process.

#!/bin/bash

alive=$( uptime | grep -ohe 'up .*' | sed 's/,//g' | awk '{ print $2 }')

until [[ $alive -lt 0 ]]; do Caffeinate -d -t 2 sleep 2 echo "This computer has been awake for $alive days" done

Eventually I'd like to have the computer hit a certain amount of days, then break and restart, automatically login, and launch the process over again to ensure that performance is not hindered by the computer being awake for months on end.

But I haven't had the time to work on that just yet ;)

AdminBee
  • 22,803
  • Sharing some possible simplifications: https://unix.stackexchange.com/a/257142/117549 and https://unix.stackexchange.com/questions/586750/trying-to-calculate-uptime-and-email-if-greater-than-a-number-of-days – Jeff Schaller Jul 16 '21 at 17:46
  • Be aware that uptime's output will vary. Less than a day will print the hours elapsed, more than that it will print timenow up x days, .... – annahri Jul 20 '21 at 06:30
  • Yes that is expected, the use of caffeinate for 2 seconds is for testing purposes. The plan is to caffeinate for a full day at least. – Emmanuel Tsavaris Aug 11 '21 at 11:48

1 Answers1

0

You need to get rid of uptime’s output to its standard error:

alive=$( uptime 2>/dev/null | grep -ohe 'up .*' | sed 's/,//g' | awk '{ print $2 }')

&>/dev/null redirects both standard output and standard error to the bit bucket, so you end up with no output to process, and your variable is set to the empty string. 2>/dev/null only redirects standard error, getting rid of any error message, but preserving the regular output.

Note that awk can do everything grep and sed can; I don’t know the exact output of uptime on your system, but on mine the following works:

alive=$(uptime 2>/dev/null | awk '/up/ { print $3 }')
Stephen Kitt
  • 434,908
  • Thank you! what does 2> do as opposed to &>? This did solve the problem. – Emmanuel Tsavaris Jul 16 '21 at 15:10
  • 2> redirects standard error, &> redirects both standard output and standard error (which is why you were losing the “normal” output from uptime). – Stephen Kitt Jul 16 '21 at 15:12
  • An alternative way to do this is 2>&-, which closes file descriptor 2, instead of sending it to /dev/null. However, a few programs don't react well to this. – ddawson Jul 16 '21 at 15:47
  • @ddawson programs are allowed to expect their standard error to be open when they start; 2>&- breaks that expectation. – Stephen Kitt Jul 16 '21 at 15:55
  • As he is using sed to get rid of commas, the uptime 2>/dev/null | awk '/up/ { print $3 }' will have a trailing comma. – annahri Jul 20 '21 at 06:18
  • @annahri only if the third field ends with a comma, which isn’t the case here apparently. (It would be better to search for day, I guess.) – Stephen Kitt Jul 20 '21 at 07:05
  • If the uptime is less than a day, it will have a comma. For example, 14:16:38 up 3:57, 0 users, load average: 0.52, 0.58, 0.59 – annahri Jul 20 '21 at 07:17
  • Yes, hence my point about searching for “day”; the script in the question assumes that there’s a number of days in the output. – Stephen Kitt Jul 20 '21 at 11:39
  • @annahri on my system (MacOS) the 4th field states the unit of measurement (mins, hours, days, etc.) and that field is what has the trailing comma. – Emmanuel Tsavaris Aug 11 '21 at 11:55