2

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 ;)

3
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 }')
9
  • Thank you! what does 2> do as opposed to &>? This did solve the problem. Jul 16 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). Jul 16 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 at 15:47
  • @ddawson programs are allowed to expect their standard error to be open when they start; 2>&- breaks that expectation. Jul 16 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 at 6:18

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.