WelcomeWelcome | FAQFAQ | DownloadsDownloads | WikiWiki

Author Topic: Inactivity Timed Shutdown in Shell  (Read 7082 times)

Offline Boss 429

  • Newbie
  • *
  • Posts: 22
Re: Inactivity Timed Shutdown in Shell
« Reply #15 on: May 24, 2017, 09:04:18 AM »
This is the error I'm seeing when trying to run it.

Offline Juanito

  • Administrator
  • Hero Member
  • *****
  • Posts: 14817
Re: Inactivity Timed Shutdown in Shell
« Reply #16 on: May 24, 2017, 09:15:49 AM »
You need to download the extension first with "tce-load -wil procps" or "tce-load -wil procps-ng"

Offline Rich

  • Administrator
  • Hero Member
  • *****
  • Posts: 11631
Re: Inactivity Timed Shutdown in Shell
« Reply #17 on: May 24, 2017, 09:20:19 AM »
Hi Boss 429
when I try to run

Code: [Select]
tce-load -I procps
I'm getting a not found error. Is there another package I need to have downloaded prior to trying to run that code?
That should be a lower case  i  in that command. Also, did you first run:
Code: [Select]
tce-load -w procps

Offline Boss 429

  • Newbie
  • *
  • Posts: 22
Re: Inactivity Timed Shutdown in Shell
« Reply #18 on: May 24, 2017, 10:09:13 AM »
I was able to download it by using:

Code: [Select]
tce-load -wil procps-ng
I did try:

Code: [Select]
tce-load -w procps
and that did not work. It gave me an error saying file not found.

Now that I have it loaded and I can watch the idle timer, would I use this code provided by Misalf to set how long it should be idle before shutdown?

Maybe something like
Code: [Select]
w -hs | awk '/tty1/ {print $3}'

Offline Misalf

  • Hero Member
  • *****
  • Posts: 1702
Re: Inactivity Timed Shutdown in Shell
« Reply #19 on: May 25, 2017, 11:52:26 AM »
Converting the format  w  provides to something useful for a script (i.e. print seconds) is kinda tricky, but I found a start point here: https://www.reddit.com/r/linux/comments/2z7oxg/linux_w_command_get_idle_time_in_seconds/

I have modified it so it only outputs the lowest value
Code: [Select]
#!/bin/sh
# Prints idle time in seconds.

f_get_idle() {
    w -hs | awk '{
    if($3 ~ /days/){
        split($3,d,"days");
        print d[1]*86400
    }
    else if($3 ~ /:|s/){
        if ($3 ~/s/) {sub(/s/,"",$3); split($3,s,"."); print s[1]}
        else if ($3 ~/m/) {split($3,m,":"); print (m[1]*60+m[2])*60}
        else {split($3,m,":"); print m[1]*60+m[2]}
    }
    else {print $3}
    }'
}

for i in $(f_get_idle) ; do
    [ -z $IDLE ] && IDLE=$i
    [ $i -lt $IDLE ] && IDLE=$i
done

echo "$IDLE"

Download a copy and keep it handy: Core book ;)

Offline Boss 429

  • Newbie
  • *
  • Posts: 22
Re: Inactivity Timed Shutdown in Shell
« Reply #20 on: July 18, 2017, 03:54:48 PM »
I apologize for the late reply, I've been caught up in other matters. I've recently had some time to dig back into this. I'm trying to take the code you provided and make it work for what I need, but I may be going about it the wrong way. I am trying to take the lowest output value to use in a condition that would be triggered once it hits a certain time (60 seconds in the test environment).

I have it set-up like this:

Code: [Select]
#!/bin/sh
# Prints idle time in seconds.

f_get_idle() {
    w -hs | awk '{
    if($3 ~ /days/){
        split($3,d,"days");
        print d[1]*86400
    }
    else if($3 ~ /:|s/){
        if ($3 ~/s/) {sub(/s/,"",$3); split($3,s,"."); print s[1]}
        else if ($3 ~/m/) {split($3,m,":"); print (m[1]*60+m[2])*60}
        else {split($3,m,":"); print m[1]*60+m[2]}
    }
    else {print $3}
    }'
}

for i in $(f_get_idle) ; do
    [ -z $IDLE ] && IDLE=$i
    [ $i -lt $IDLE ] && IDLE=$i
done

if ("$IDLE">60)
then
sudo poweroff
fi

Offline curaga

  • Administrator
  • Hero Member
  • *****
  • Posts: 11044
Re: Inactivity Timed Shutdown in Shell
« Reply #21 on: July 19, 2017, 04:00:47 AM »
Shell tests use square brackets, and > is a string operator. Try
Code: [Select]
if [ "$IDLE" -gt 60 ]; then
The only barriers that can stop you are the ones you create yourself.

Offline Boss 429

  • Newbie
  • *
  • Posts: 22
Re: Inactivity Timed Shutdown in Shell
« Reply #22 on: July 21, 2017, 01:56:12 PM »
I tried what you suggested, and I'm no longer getting any errors, but it's still not powering off when it should be. Is there a way to monitor the script and see where the issue is at?

Offline Misalf

  • Hero Member
  • *****
  • Posts: 1702
Re: Inactivity Timed Shutdown in Shell
« Reply #23 on: July 22, 2017, 09:00:53 AM »
I made it a little bit more fancy to make things easier.
Code: [Select]
#!/bin/sh
#
# Prints idle time in seconds
# ... or waits TIME seconds while idle then beeps
# ... or waits TIME seconds while idle then executes COMMAND.
#
# Copyleft Misalf 2017

SLEEP="2" # How long to wait between checks for idle time.

TIME="$1"
shift
COMMAND="$@"

# Requires  w  from  procps .
TCUSER="$(cat /etc/sysconfig/tcuser)"
[ -n "$TCUSER" ] && su -c "tce-load -i procps >/dev/null" - "$TCUSER"

f_print_usage() {
    echo "Usage: $(basename $0) [TIME [COMMAND]]"
    echo ""
    echo "Without arguments just prints idle time in seconds and exits."
    echo "If TIME is given, beeps if idle for TIME seconds and exits."
    echo "If TIME and COMMAND is given, executes COMMAND if idle for TIME seconds and exits."
}

f_get_idle() {
    w -hs | awk '{
    if($3 ~ /days/){
        split($3,d,"days");
        print d[1]*86400
    }
    else if($3 ~ /:|s/){
        if ($3 ~/s/) {sub(/s/,"",$3); split($3,s,"."); print s[1]}
        else if ($3 ~/m/) {split($3,m,":"); print (m[1]*60+m[2])*60}
        else {split($3,m,":"); print m[1]*60+m[2]}
    }
    else {print $3}
    }'
}

f_get_lowest_idle() {
    IDLE=""
    for i in $(f_get_idle) ; do
        [ -z "$IDLE" ] && IDLE="$i"
        [ "$i" -lt "$IDLE" ] && IDLE="$i"
    done
}

if [ -n "$TIME" ] ; then
    case $TIME in
    ''|*[!0-9]*)
        echo "Cannot wait \"$TIME\" seconds."
        echo ""
        f_print_usage
        exit 1
    ;;
    esac
    if [ -n "$COMMAND" ] ; then
        #echo "Will run \"$COMMAND\" if idle for \"$TIME\" seconds..."
        while true ; do
            f_get_lowest_idle
            if [ "$IDLE" -ge "$TIME" ] ; then
                #echo "\"$IDLE\" seconds reached."
                eval "$COMMAND"
                break
            fi
            sleep "$SLEEP"
        done
    else
        #echo "Will beep if idle for \"$TIME\" seconds..."
        while true ; do
            f_get_lowest_idle
            if [ "$IDLE" -ge "$TIME" ] ; then
                echo "*BEEP*"
                echo -en "\033[10;110]\033[11;100]\007" > /dev/tty0
                usleep 110000
                echo "*BOOP*"
                echo -en "\033[10;55]\033[11;100]\007" > /dev/tty0
                break
            fi
            sleep "$SLEEP"
        done
    fi
else
    f_get_lowest_idle
    echo "$IDLE"
fi


You could
Code: [Select]
idle.sh 10 echo test &
which prints the word "test" after 10 seconds of inactivity.

Or
Code: [Select]
idle.sh 3600 sudo poweroff &
which shuts down after 1 hour of inactivity.
In such a case where the command is executed after a long idle time,
and it doesn't need to be executed exactly at that second,
it might make sense to increase the value of the  SLEEP  variable to like 60 or so.

Or
Code: [Select]
idle.sh 10 &
which makes beep boop after 10 seconds of inactivity (if you have a PC speaker).
Download a copy and keep it handy: Core book ;)

Offline Boss 429

  • Newbie
  • *
  • Posts: 22
Re: Inactivity Timed Shutdown in Shell
« Reply #24 on: July 24, 2017, 03:29:14 PM »
Thank you! I was able to get it to work, but it keeps asking for tc account's password now?

Offline Misalf

  • Hero Member
  • *****
  • Posts: 1702
Re: Inactivity Timed Shutdown in Shell
« Reply #25 on: July 25, 2017, 02:48:50 PM »
Oh, true.
That's due to use of the  su  command for loading the  procps  extension.
I've added a check for root so entering the password shouldn't be needed anymore.
I've also changed it from  procps  to  procps-ng.
Code: [Select]
#!/bin/sh
#
# Prints idle time in seconds
# ... or waits TIME seconds while idle then beeps
# ... or waits TIME seconds while idle then executes COMMAND.
#
# Copyleft Misalf 2017

SLEEP="2" # How long to wait between checks for idle time.

TIME="$1"
shift
COMMAND="$@"

# Requires  w  from  procps .
TCUSER="$(cat /etc/sysconfig/tcuser)"
if [ -n "$TCUSER" ] ; then
    if [ "$(id -u)" -eq 0 ] ; then
    su -c "tce-load -i procps-ng >/dev/null" - "$TCUSER"
    else
    tce-load -i procps-ng >/dev/null
    fi
fi

f_print_usage() {
    echo "Usage: $(basename $0) [TIME [COMMAND]]"
    echo ""
    echo "Without arguments just prints idle time in seconds and exits."
    echo "If TIME is given, beeps if idle for TIME seconds and exits."
    echo "If TIME and COMMAND is given, executes COMMAND if idle for TIME seconds and exits."
}

f_get_idle() {
    w -hs | awk '{
    if($3 ~ /days/){
        split($3,d,"days");
        print d[1]*86400
    }
    else if($3 ~ /:|s/){
        if ($3 ~/s/) {sub(/s/,"",$3); split($3,s,"."); print s[1]}
        else if ($3 ~/m/) {split($3,m,":"); print (m[1]*60+m[2])*60}
        else {split($3,m,":"); print m[1]*60+m[2]}
    }
    else {print $3}
    }'
}

f_get_lowest_idle() {
    IDLE=""
    for i in $(f_get_idle) ; do
        [ -z "$IDLE" ] && IDLE="$i"
        [ "$i" -lt "$IDLE" ] && IDLE="$i"
    done
}

if [ -n "$TIME" ] ; then
    case $TIME in
    ''|*[!0-9]*)
        echo "Cannot wait \"$TIME\" seconds."
        echo ""
        f_print_usage
        exit 1
    ;;
    esac
    if [ -n "$COMMAND" ] ; then
        #echo "Will run \"$COMMAND\" if idle for \"$TIME\" seconds..."
        while true ; do
            f_get_lowest_idle
            if [ "$IDLE" -ge "$TIME" ] ; then
                #echo "\"$IDLE\" seconds reached."
                eval "$COMMAND"
                break
            fi
            sleep "$SLEEP"
        done
    else
        #echo "Will beep if idle for \"$TIME\" seconds..."
        while true ; do
            f_get_lowest_idle
            if [ "$IDLE" -ge "$TIME" ] ; then
                echo "*BEEP*"
                echo -en "\033[10;110]\033[11;100]\007" > /dev/tty0
                usleep 110000
                echo "*BOOP*"
                echo -en "\033[10;55]\033[11;100]\007" > /dev/tty0
                break
            fi
            sleep "$SLEEP"
        done
    fi
else
    f_get_lowest_idle
    echo "$IDLE"
fi

Download a copy and keep it handy: Core book ;)

Offline Boss 429

  • Newbie
  • *
  • Posts: 22
Re: Inactivity Timed Shutdown in Shell
« Reply #26 on: July 26, 2017, 03:48:15 PM »
I have added this script into a current batch file that I have running upon startup, when this executes, it is immediately shutting down the terminal. it appears to not be looking at the value behind the command. When I run the command on its' own, it executes properly though. My batch script looks like this:

Code: [Select]
while [ -z “$( ifconfig eth0 | grep ‘inet addr’ )” ] ; do sleep 1 ; done
/home/tc/Idle.sh 60 sudo poweroff
while telnet xxx.xxx.xxx.xxx ; do wait ; done

I have tried using it this way as well

Code: [Select]
telnet xxx.xxx.xxx.xxx & if /home/tc/Idle.sh 60
then sudo poweroff
fi

I also tried a few variations of using parenthesis to try and isolate the time, to no avail. I have to be missing something simple here.. I'm going to keep working at it, I just want to make sure I'm not missing something.

Offline Boss 429

  • Newbie
  • *
  • Posts: 22
Re: Inactivity Timed Shutdown in Shell
« Reply #27 on: July 27, 2017, 01:37:20 PM »
After working on it some more.. I was able to get it to execute while running the telnet command, the *BEEP* and *BOOP* message/sound both work, but after that, it doesn't shut down like it should. It seems like the telnet command may be stopping the shutdown part of the command from running?

Offline Misalf

  • Hero Member
  • *****
  • Posts: 1702
Re: Inactivity Timed Shutdown in Shell
« Reply #28 on: July 29, 2017, 06:58:14 AM »
You can run the  idle.sh  shell script directly at the start of your shell script.
It's meant to run in the background and monitor inactivity forever.
To run it in the background, add an ampersand ("&") at the end of the command so that the shell doesn't wait for it to complete and executes the next command.

Code: [Select]
/home/tc/idle.sh 3600 sudo poweroff &
while [ -z "$(ifconfig eth0 | grep "inet addr")" ] ; do sleep 1 ; done
...

You could also run  idle.sh  from  /opt/bootlocal.sh  instead.
Download a copy and keep it handy: Core book ;)