Tiny Core Linux
Tiny Core Base => TCB Q&A Forum => Topic started 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
-
xset is provided by Xlibs.tcz .
Including its deps it's 3.09 MB.
-
For a cli-only setup, try "w" from procps.tcz.
-
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.
-
Oops, sorry. Kinda makes sense that xset can't set properties of X when there is no X. :p
-
Is there a way it will work without X?
-
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 .
-
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.
-
I've looked into it a little more, I'm still not having a lot of luck getting it to work..
-
tce-load -i procps
watch w
You should see the IDLE value increasing.
-
Maybe something like
w -hs | awk '/tty1/ {print $3}'
-
when I try to run
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?
-
You don't mention your version and arch. We assume the latest on x86, where procps is available.
-
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..
-
procps-ng seems to be available there, it has the same command.
-
This is the error I'm seeing when trying to run it.
-
You need to download the extension first with "tce-load -wil procps" or "tce-load -wil procps-ng"
-
Hi Boss 429
when I try to run
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:
tce-load -w procps
-
I was able to download it by using:
tce-load -wil procps-ng
I did try:
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
w -hs | awk '/tty1/ {print $3}'
-
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
#!/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"
-
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:
#!/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
-
Shell tests use square brackets, and > is a string operator. Try
if [ "$IDLE" -gt 60 ]; then
-
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?
-
I made it a little bit more fancy to make things easier.
#!/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
idle.sh 10 echo test &
which prints the word "test" after 10 seconds of inactivity.
Or
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
idle.sh 10 &
which makes beep boop after 10 seconds of inactivity (if you have a PC speaker).
-
Thank you! I was able to get it to work, but it keeps asking for tc account's password now?
-
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.
#!/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
-
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:
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
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.
-
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?
-
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.
/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.