How to get the time when I last used the computer - linux

In GNU/Linux on xorg session, what I want to do is to get how many seconds have passed since I stopped working with the computer (i.e. no keys pressed and/or cursor moved).
Running in the background, the script below will display secs in the status bar.
But the question is what THE_COMMAND will be.
While true; do
last_touched="$(THE_COMMAND)"
now="$(date +%s)"
secs=$((now - last_touched))
echo "${secs} seconds ago"
sleep 3
done

I remember asking the same question a while back.
Here is what I found,
last -aiF -n 1 userName
command can give you the current session.
When combined with awk you can get the result as follows
$ last -aiF -n2 username
username :1 Wed Apr 21 13:09:00 2021 still logged in 0.0.0.0
username :1 Wed Apr 21 07:28:47 2021 - down (05:39) 0.0.0.0
$ last -aiF -n 2 ogulcan | awk '{print $10}'
in
(05:39)
the lines here are the session times.
These times are counted as now - first boot login
But I believe these does not work best for you.
So here is the 8 year old question that may be helpful to you.
User Idle time in Linux
Using python you can calculate the idle time passed. Maybe this way, you can simply get what you want with python.

Related

Calculating the time until the start of next hour in Bash

Hi I have a bash script called by a systemd service that needs to run until the start of the next hour. Currently I have been using:
currentTime=$(date +"%s")
nextHour=$(date -d "$(date -d 'next hour' '+%H:00:00')" '+%s')
duration=$(((nextHour-currentTime)*1000))
Which works except for trying to calculate the difference between 11pm and midnight were as far as I can tell it gets the current days midnight from 23 hours previous.
Oct 13 23:00:05 host bash[2019]: 1665698405
Oct 13 23:00:05 host bash[2019]: 1665615600
Oct 13 23:00:05 host bash[2019]: -82805000
I figure I could put a conditional check with a different calculation if needed or perhaps look at a systemd timer for triggering the service but as the service needs to always activate on boot/reboot as well as running hour to hour this setup seemed more appropriate.
Would appreciate any advice on why this is happening and advice on most streamlined steps to avoid it.
This isn't really a question about bash, but seems to be more about date. Given that date has multiple different implementations, it seems wiser to choose a different tool to do the calculation. I suspect perl is more standardized and (almost) as available as date, so you might try to get the difference with:
perl -MTime::Seconds -MTime::Piece -E '
my $t = localtime; my $m = ($t + ONE_HOUR)->truncate(to => "hour"); say $m - $t'

get average of times that take job finish in for loop shell script

Here is my first shell script
#!/bin/bash
COUNTER=0
while [ $COUNTER -lt 10000 ]; do
date;
time wget -q 'http://exmple.com/' > /dev/null | grep real;
sleep 3;
let COUNTER=COUNTER+1
done
echo ${COUNTER} Request Sent\n
Average Response Time is :
this script download page content and calculate time of page response
i need to store Real parameter and calculate average of it
the output of script is something like that
Tue Oct 25 22:43:36
real 0m13.275s
user 0m0.004s
sys 0m0.008s
So my problems are :
How can i add some jobs (like echo ${COUNTER} ) after pressing crtl+c (stopping script)
How can i store value of "real" in seconds // sometimes page response goes to minutes , so basically need some time convert function (?)
i tried to solve the problems but as i mentioned i am training shell script
#!/bin/bash
echo "How many runs would you like to perform?"
read limit
total_time=0
counter=1
while [ ${counter} -le ${limit} ]
do
date
run_time=`(time -p wget -qO- http://exmple.com/) 2>&1 > /dev/null | grep real | awk '{print $2}'`
echo "Run ${counter} completed in ${run_time} seconds"
total_time=$(bc<<<"${total_time}+${run_time}")
if [ ${counter} -ne ${limit} ]
then
sleep 3
let counter=counter+1
fi
done
avg=$(printf "%.3f" "$(bc -l <<<"${total_time}/${limit}")")
echo "${counter} requests were sent taking ${total_time} seconds"
echo "Average response time was : ${avg} seconds"
Above is a modified script to perform the operations you requested, with a couple modifications
Added a question then input to ask how many runs to make each time, instead of a static number
Print out total time for runs and then average per run in 3 decimal places
Skip sleeping if it's the last run
You'll notice we use bc instead of let for a couple math lines. The bc command allows the use of decimal places.
https://www.gnu.org/software/bc/manual/html_mono/bc.html
To get the value in seconds I had to use awk to separate the value from the title 'real' in the line. Then you can do the math on the number value.
One other thing I noticed in your initial script. You used both ways of displaying a variable:
$COUNTER and ${COUNTER}
While both are legitimate, I got into the habit of always encapsulating my variables, it makes things easier when you want to add to the end of it.
For example let's say I have a number defined (NUM=7), but want to display it times 10. If I don't encapsulate echo $NUM0 then I get an error because the variable $NUM0 wasn't defined. But if I encapsulate echo ${NUM}0 will display an output of 70.
All of this results in a final output as below
How many runs would you like to perform?
5
Tue Oct 25 16:02:58 MST 2016
Run 1 completed in 0.09 seconds
Tue Oct 25 16:03:01 MST 2016
Run 2 completed in 0.08 seconds
Tue Oct 25 16:03:05 MST 2016
Run 3 completed in 0.07 seconds
Tue Oct 25 16:03:08 MST 2016
Run 4 completed in 0.09 seconds
Tue Oct 25 16:03:11 MST 2016
Run 5 completed in 0.08 seconds
5 requests sent taking .41 seconds
Average response time was : 0.08 seconds
Please let me know if you have any other questions about the script.
You can record a reasonably precise time with e.g.
t1=$(date +%s.%N)
wget ...
t2=$(date +%s.%N)
diff=$(($t2-$t1))
For doing stuff after Ctrl+C, which is really a SIGINT signal, read up about the trap builtin.

Bash: Program next execution of current script using 'at'

I want to execute a script and make it schedule the next execution. A sample would be:
#!/bin/bash
TMP=/tmp/text.txt
SCRIPT=$(readlink -f $0)
date >>$TMP
at -f $SCRIPT now + 1 minutes >>$TMP 2>&1
echo -e "\n" >>$TMP
A sample execution would do as follows:
First execution OK. Schedules to next minute
Second execution writes OK but doesn't schedule
Resulting output would be:
tue mar 5 14:34:01 CET 2013
job 15 at 2013-03-05 14:35
tue mar 5 14:35:00 CET 2013
job 16 at 2013-03-05 14:36
[now at 2013-03-05 14:38]
atq outputs nothing and I don't see any /var/at/jobs (In fact, ls /var/at* outputs nothing. There is no message in any user in /var/mail/. I'm trying on a CentOS release 5.6 x86_64
Anyone has any hint as to what may be happening?
suspectus, you have hit the point... echo $SCRIPT gives '/bin/bash'... I've manually written the full path and now it works

Perform action when user logs in via SSH from a particular host

I have a quesiton that puzzles me and I wonder if anyone has attempted to achieve the following:
Let's assume that this is the result of my 'last' command in a Linux environment:
root pts/1 192.168.1.10 Wed Feb 10 07:04 - 07:57 (00:52)
root pts/2 Tue Feb 9 22:00 - 00:13 (02:13)
How can I setup a particular action (say for example a modified MOTD or sending an email) if the the 'root' user has logged in from 192.168.1.10. Is there a way of capturing this information?
The second part of this question is that how can I make the above check a bit more robust - i.e. if I have the following:
mary pts/1 192.168.1.10 Wed Feb 10 07:04 - 07:57 (00:52)
bob pts/2 Tue Feb 9 22:00 - 00:13 (02:13)
Now I'd like to perform an action if the username is equal to 'mary' and the host is 192.168.1.10.
Any suggestions are welcomed.
Thank you in advance.
There's a special file /etc/ssh/sshrc where you can put some commands that will runs each time someone connect by ssh. I wrote that for you :
#!/bin/bash
mail=user#domain.tld
monitored_user=root
monitored_ip=x.x.x.x
hostname=$(hostname)
# add a welcome message:
printf >&2 "\nWelcome on $hostname $USER\n"
read -d " " ip <<< $SSH_CONNECTION
[[ $ip == $monitored_ip && $USER == $monitored_user ]] || exit 0
date=$(date "+%d.%m.%Y %Hh%M")
reverse=$(dig -x $ip +short)
mail -s "Connexion of $USER on $hostname" $mail <<EOF
IP: $ip
Reverse: $reverse
Date: $date
EOF
Put this script in a file, then put the full path of the script in /etc/ssh/sshrc
In man ssh :
/etc/ssh/sshrc :
Commands in this file are executed by ssh when the user
logs in, just before the user's shell (or command) is started. See the
sshd(8) manual page for more information.
Thanks for all your replies. Eventually I managed to find a solution which does work for the time being but it does have one flaw which I'll point out in a minute.
I have added the following to my /etc/bashrc file (or /etc/bash.bashrc whatever environment you're using):
HOST="192.168.0.1"
RHOST=`who am i | sed -n 's/.*(\([^) ]*\).*/\1/p; 1q'`
if [ "$RHOST" == "$HOST" ]; then
echo "SAY WHAT!"
#add further actions here if needed
fi
The flaw that I was talking about before may actually not be a flaw. If you're already SSH-ed into the system, and you want to SSH to a host which lives on the same IP, say ssh root#your-host who am i would then print 'your-host' but I think that's the way it should be.
Needless to say that the above sed statement can be modified so you can capture the username as well, and you can extend the if/else statement to suite your needs.
Thank you again for all your replies.
You can add something to /etc/profile or equivalent that does something depending on the value of $SSH_CLIENT.
It looks like you are using last because it reads /var/log/wtmp by default which is a record of logins. The who command also allows you to read the same file but with an interface more to your needs.
For example:
$ who --ips /var/log/wtmp | grep '^msw.*127.0.0.1'
msw pts/2 2012-10-07 15:52 127.0.0.1
msw pts/3 2012-10-07 15:55 127.0.0.1
where neither of those sessions were active, but rather historic and logged.
In ubuntu i put a script in
/etc/profile.d
and when someone(user ssh) log in, it send an email to my mail
#/etc/profile.d/run_on_loggin.sh
echo $(who i am) | mail -s 'SSH Login Notification' mymail#hotmail.com
I want to create a php file with smtp, to send email with my mail to me...
some times hotmail saved in spam...
if i have the php file i will run like this...
if i want to pass var to file php run like this...
excuse my english :3
note: i think this command run from user, be carefully if the user doen't has permission to use some command or send email.
One way would be to run a simple script periodically:
#!/bin/bash
users=$(last | sed -ne '/192\.168\.1\.10/ s/\([^ ]*\).*/\1/p')
for user in $users; do
sendmail "$user" < email.txt
done
This would pipe the last command into sed to extract a user list and save it into the variable $users. The sed command uses the -n flag so it only prints what we tell it to. First, we select lines that contain the specified IP, with the /192\.168\.1\.10/ "address". On those lines, we attempt to extract the characters before a space, and if we succeed we print the result.
Then, we can loop through the $users variable and act accordingly.
One way to call this repeatedly would be through cron, and a simpler way would be to do while true; do ./my_script.bash; sleep 60; done.

Is there a variable in Linux that shows me the last time the machine was turned on?

I want to create a script that, after knowing that my machine has been turned on for at least 7h, it does something.
Is this possible? Is there a system variable or something like that that shows me the last time the machine was turned on?
The following command placed in /etc/rc.local:
echo 'touch /tmp/test' | at -t $(date -d "+7 hours" +%m%d%H%M)
will create a job that will run a touch /tmp/test in seven hours.
To protect against frequent reboots and prevent adding multiple jobs you could use one at queue exclusively for this type of jobs (e.g. c queue). Adding -q c to the list of at parameters will place the job in the c queue. Before adding new job you can delete all jobs from c queue:
for job in $(atq -q c | sed 's/[ \t].*//'); do atrm $job; done
You can parse the output of uptime I suppose.
As Pavel and thkala point out below, this is not a robust solution. See their comments!
The uptime command shows you how long the system has been running.
To accomplish your task, you can make a script that first does sleep 25200 (25200 seconds = 7 hours), and then does something useful. Have this script run at startup, for example by adding it to /etc/rc.local. This is a better idea than polling the uptime command to see if the machine has been up for 7 hours (which is comparable to a kid in the backseat of a car asking "are we there yet?" :-))
Just wait for uptime to equal seven hours.
http://linux.die.net/man/1/uptime
I don't know if this is what you are looking for, but uptime command will give you for how many computer was running since last reboot.
$ cut -d ' ' -f 1 </proc/uptime
This will give you the current system uptime in seconds, in floating point format.
The following could be used in a bash script:
if [[ "$(cut -d . -f 1 </proc/uptime)" -gt "$(($HOURS * 3600))" ]]; then
...
fi
Add the following to your crontab:
#reboot sleep 7h; /path/to/job
Either /etc/crontab, /etc/cron.d/, or your users crontab, depending on whether you want to run it as root or the user -- don't forget to put "root" after "#reboot" if you put it in /etc/crontab or cron.d
This has the benefit that if you reboot multiple times, the jobs get cancelled at shut down, so you won't get a bunch of them stacking up if you reboot several times within 7 hours. The "#reboot" time specification triggers the job to be run once when the system is rebooted. "sleep 7h;" waits for 7 hours before running "/path/to/job".

Resources