Tiny Core Linux

Tiny Core Base => TCB Q&A Forum => Topic started by: Boss 429 on May 11, 2017, 11:14:39 AM

Title: Inactivity Timed Shutdown in Shell
Post by: Boss 429 on May 11, 2017, 11:14:39 AM
I have been digging around in the forums looking for a way to shut down Linux in shell after a period of inactivity. I found this thread from 2014: http://forum.tinycorelinux.net/index.php/topic,17830.0.html. I used the code Rich provided, and it seems to almost work. When it is executed, it says that it doesn't find xset (probably because there is no "X" installed on this machine). I just need something I can point to that will consistently say the pc is inactive, or that there have been no keystrokes after a period of time, in shell.

Thank you
Title: Re: Inactivity Timed Shutdown in Shell
Post by: Misalf on May 11, 2017, 11:31:28 AM
xset  is provided by  Xlibs.tcz .
Including its deps it's 3.09 MB.
Title: Re: Inactivity Timed Shutdown in Shell
Post by: curaga on May 11, 2017, 01:41:48 PM
For a cli-only setup, try "w" from procps.tcz.
Title: Re: Inactivity Timed Shutdown in Shell
Post by: Boss 429 on May 15, 2017, 10:24:05 AM
I have downloaded and installed Xlibs.tcz. when I try to run Xset -s it is giving me the error "xset: unable to open display "" "

I also tried downloading procps.tcz, and it is giving me an error saying file not found.
Title: Re: Inactivity Timed Shutdown in Shell
Post by: Misalf on May 15, 2017, 10:48:48 AM
Oops, sorry. Kinda makes sense that xset can't set properties of X when there is no X. :p
Title: Re: Inactivity Timed Shutdown in Shell
Post by: Boss 429 on May 15, 2017, 11:35:39 AM
Is there a way it will work without X?
Title: Re: Inactivity Timed Shutdown in Shell
Post by: Misalf on May 16, 2017, 06:33:25 AM
I also tried downloading procps.tcz, and it is giving me an error saying file not found.
On tc-7.x x86  procps.tcz  contains  /usr/local/bin/w .
Title: Re: Inactivity Timed Shutdown in Shell
Post by: Boss 429 on May 17, 2017, 08:43:20 AM
So, referring back to what Rich had provided for code in the other thread, how would I go about making it shut down after 5 hours? I'm not sure how I need to set up the code and what exactly it will need to look at in order for it to work properly.
Title: Re: Inactivity Timed Shutdown in Shell
Post by: Boss 429 on May 23, 2017, 08:51:16 AM
I've looked into it a little more, I'm still not having a lot of luck getting it to work..
Title: Re: Inactivity Timed Shutdown in Shell
Post by: Misalf on May 23, 2017, 09:31:05 AM
Code: [Select]
tce-load -i procps
watch w
You should see the  IDLE  value increasing.
Title: Re: Inactivity Timed Shutdown in Shell
Post by: Misalf on May 23, 2017, 09:35:36 AM
Maybe something like
Code: [Select]
w -hs | awk '/tty1/ {print $3}'
Title: Re: Inactivity Timed Shutdown in Shell
Post by: Boss 429 on May 23, 2017, 10:12:42 AM
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?
Title: Re: Inactivity Timed Shutdown in Shell
Post by: curaga on May 23, 2017, 02:41:33 PM
You don't mention your version and arch. We assume the latest on x86, where procps is available.
Title: Re: Inactivity Timed Shutdown in Shell
Post by: Boss 429 on May 23, 2017, 03:17:50 PM
My apologies, I'm running PiCore 9.0 on a couple (including the test machine), and Core 7.2 on the others. Would like to have it working on both if possible..
Title: Re: Inactivity Timed Shutdown in Shell
Post by: curaga on May 24, 2017, 07:31:32 AM
procps-ng seems to be available there, it has the same command.
Title: Re: Inactivity Timed Shutdown in Shell
Post by: Boss 429 on May 24, 2017, 09:04:18 AM
This is the error I'm seeing when trying to run it.
Title: Re: Inactivity Timed Shutdown in Shell
Post by: Juanito 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"
Title: Re: Inactivity Timed Shutdown in Shell
Post by: Rich 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
Title: Re: Inactivity Timed Shutdown in Shell
Post by: Boss 429 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}'
Title: Re: Inactivity Timed Shutdown in Shell
Post by: Misalf 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"

Title: Re: Inactivity Timed Shutdown in Shell
Post by: Boss 429 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
Title: Re: Inactivity Timed Shutdown in Shell
Post by: curaga 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
Title: Re: Inactivity Timed Shutdown in Shell
Post by: Boss 429 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?
Title: Re: Inactivity Timed Shutdown in Shell
Post by: Misalf 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).
Title: Re: Inactivity Timed Shutdown in Shell
Post by: Boss 429 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?
Title: Re: Inactivity Timed Shutdown in Shell
Post by: Misalf 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

Title: Re: Inactivity Timed Shutdown in Shell
Post by: Boss 429 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.
Title: Re: Inactivity Timed Shutdown in Shell
Post by: Boss 429 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?
Title: Re: Inactivity Timed Shutdown in Shell
Post by: Misalf 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.