# Uptime Since... (#174)

**URL:** <https://www.ruby-forum.com/t/uptime-since-174/147145>\
**Category:** Ruby\
**Created:** [August 28, 2008, 7:49pm UTC](https://www.ruby-forum.com/t/uptime-since-174/147145 "2008-08-28T19:49:23Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![mansfiem](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/fbc32d/32.png) [@mansfiem](https://www.ruby-forum.com/u/mansfiem)\
**Post date:** [August 28, 2008, 7:49pm UTC](https://www.ruby-forum.com/t/uptime-since-174/147145/1 "2008-08-28T19:49:23Z")

</div>

First thing: the quiz name is off. Really, it should properly have  
been called “Up Since…”, as we’re looking for the time of reboot.  
The `uptime` command was in my mind, though, which is why the title is  
strange.

There are a number of ways to attack this problem, as shown in the  
variety of the solutions. First, let’s look at “the right way” to  
solve this problem: use a library or module that does the work for  
you. Such was _Daniel B._'s solution, shown here:

```
require 'sys/uptime'
p Sys::Uptime.uptime

```

Unfortunately, this didn’t work on my machine, and hopefully that’s  
only because of an outdated version of rb-sys-uptime, or some similar  
reason. I’ll take Daniel’s word that this works on his, though I  
wonder whether he’s returning the uptime or the time of last reboot  
(as requested). Still, with such a module that abstracts the platform  
differences, this is an easy win… if you get it to work. (Offhand,  
this seems to be a Darwin, i.e. Mac OS X, module; if true, then it’s  
not “the right way” for other platforms.)

Let’s go on to the submission from _Erik H._, which isn’t even  
Ruby code.

```
last | grep reboot | head -1

```

Sometimes the Unix way is the best way. Of course, you need to know  
where this information resides, and there may still be platform  
differences (along with significant command-line differences on  
Windows), but this is a simple and quick one-liner that requires only  
a few common tools.

Let’s look now at some Ruby code. We’ll look first at _Jesus  
Gabriel_’s second submission:

```
captures = (`uptime`.match /up (?:(?:(\d+)

```

days,)?\s+(\d+):(\d+)|(\d+) min)/).captures  
elapsed\_seconds = captures.zip([86440, 3600, 60, 60]).inject(0) do  
|total, (x,y)|  
total + (x.nil? ? 0 : x.to\_i \* y)  
end  
puts “Last reboot was on #{Time.now - elapsed\_seconds}”

The uptime information is gathered from the call to `uptime`. Note the  
backticks, which indicate that this is a shell command to be executed,  
and its output returned. The output is matched against a regular  
expression, containing a number of groups, several of which are  
optional. Four of those groups, however, are returned, to match  
against days, hours or minutes passed. (The minutes may be grouped in  
one of two ways.)

The captured results are paired up with the array `[86440, 3600, 60, 60]`, each entry corresponding to the number of seconds in a day, hour  
or minute. Finally, using inject, the total number of seconds since  
the last reboot is determined. Subtracting this from `Time.now`  
results in the time of the last reboot.

A few comments… As was mentioned on the mailing list, the regular  
expression to match the output of `uptime` is fragile. A few  
variations were shown to exist. A more complex regular expression  
might be able to capture more variants, though the better answer is  
not to call `uptime` as a shell command, but rather use the  
appropriate system services to access the information directly.  
However, all this parsing is a direct result of my asking for it, so  
for this quiz, I’m not too concerned about this problem.

What I found a bit interesting (or confusing) was the different  
classes available for date/time information: `Date`, `Time` and  
`DateTime`. My own solution used `DateTime`, which I wrongly assumed I  
would need (thinking `Time` was only time information). I should have  
explored more, since the `Time` solution seems simpler.

Additionally, one subtracts _days_ from `DateTime` objects, but  
subtracts _seconds_ from `Time` objects. `Time` supports a `now`  
method, while `DateTime` does not. I expect there is some amount of  
logic to these classes, but it seems to have escaped me this time  
around.

One last comment on Jesus’ solution. The `uptime` shell command  
provides the current time simultaneously with the elapsed time since  
last reboot. Yet his solution uses `Time.now` rather than the provide  
time. For this quiz, it’s not big thing: the answer would, at most, be  
off by one minute. Still, it may be an important consideration for  
other scripts to preserve the matching time, to ensure accuracy.

Make sure to take a look at the other solutions. In particular, the  
Windows solution from _Gordon T._ which makes use of an  
operating system module to get the last reboot time directly. Also,  
from _Jesse M._ is a solution that access the process file  
system.
