Category Archives: Linux Tools

UFTP: Mass File Distribution Using Multicasting

Introduction

Multicasting has it’s pros and cons just like everything else. But it is often an overlooked solution to a common business problem which is: How do I transfer a file to multiple (subscribed) locations at the same time?
Most administrators or developers will come up with a solution that involves sending this file to each site using a common protocol such as SFTP, SCP, RSYNC, FTP, RCP, etc. There is no doubt that these solutions will work. However these solutions require you to send the file to each location individually. Hence, if you need to send a 10MB file to 100 remote locations, you’ll need 1GB (10MB x 100) of local network bandwidth to do it with.
Traditional Protocol File Transfers
A Multicasting solution saves you this effort and bandwidth by allowing you to send the file once and have all 100 sites collectively store it onto their systems at (relatively) the same time. Now, with respect to the diagram below (and the rest of this blog), I’m focusing entirely on the amazing efforts Dennis Bush put into UFTP. It is this tool that makes all of this possible. UFTP is one of those diamonds in the rough that I don’t think gets enough attention for the value it brings with it.
Multicast File Transfer using UFTP

Multicast in a Nutshell

A Multicast boils down to just being an IP address anywhere in the 224.0.0.0/4 network range. It uses a User Datagram Protocol to communicate with anyone who chooses to read and write data from this address. Routers can be configured to share this address across networks so that everyone may join in. Similar to a chat room on the internet where everyone joins together and anything they write, everyone else in the channel can see too.

Multicasting no doubt has it’s drawbacks. But I figure that it’s not worth dwelling on what you can’t do with the (multicast) protocol on it’s own since the UFTP tool this blog focuses on for mass file distribution has solved many (if not all) of these problems for us.

Why Multicasting, Who Uses it?

Multicasting saves bandwidth. Think of your Cable TV provider; when you change a channel, you’re actually just subscribing to a new multicast address along with the 100+ million other subscribing customers. Multicasting allows Cable TV companies to broadcast every channel at once, and those who are interested in a specific channel will receive it. Regardless of what channel you change to, there is no additional load sustained by the cable provider.

System administrators may not even know they’re using it when if they are managing a cluster. Most clusters use multicast as a way of passing their heartbeats to all other nodes in efforts to keep quorum.

Now, with respect to UFTP, if you visit it’s official website, you’ll see that the the Wall Street Journal used this tool in the past to send their developed newspapers to remote printing plants and other outlets across the United States.

UFTP in a Nutshell

UFTP is a File Transfer solution that wraps itself around the the multicast protocol as well as addressing the deficiencies that come with it. It is a well designed server/client application that allows for one to easily transfer files from 1 location to as many clients as you want in one shot. It can drastically save your company on bandwidth and has been around long enough to be deemed a reliable business decision. It’s worth noting that UFTP was written in C making it incredibly fast and lightweight on system resources. It works on all platforms but I’ll specifically focus on CentOS and the rpms I’ve packaged.

To use the software, you simply pass it a file and it looks after all the dirty work of guaranteeing it’s delivery to all of the clients subscribed to the address it broadcasts on. The author thought of everything when developing his tool, encryption of the data is always available to you as well if you prefer. He developed 3 main tools that you can manipulate to feed your data anywhere.
A Simple UFTP Environment

  • uftp (The Server – Docs): A simple command line tool that takes a file and broadcasts it to all of the listening clients. This is the exact reverse of the traditional ftp, sftp, scp, etc tools where they become the client and need to connect to a server to preform their tasks.
  • uftpd (The Client – Docs): A daemon that starts up and listens to a multicast address for new files being broadcasted by the server. Again, you’ll notice with Multicasting, roles are reversed from what you’d normally be used to. With the traditional protocols (FTP, SFTP, SCP, etc), they usually have daemons to host the server side of things not the client. You’ll want to run this daemon at all locations you wish to receive content broadcasted by the server (uftp).
  • uftpproxyd (The Proxy – Docs): The proxy allows you to tunnel your uftp multicast across a network that doesn’t support multicasting (such as the internet). This allows clients in other controlled networks (separated by one you can’t control) to additionally be part of your file distribution.

    The UFTP Proxy has 3 main modes it operates as:

    • Server Mode: This is used for pushing content upstream. This would effectively sit on the same server you call ‘uftp’ from. It listens just like any other client would and passes all information it receives to connected UFTP Proxies configured with the client mode.
    • Client Mode: This communicates with a UFTP Proxy configured for Server Mode and mimics the ‘uftp’ by broadcasting the same data to the local multicast address. This allows all local UFTP Clients to retrieve the file(s).
    • Response Mode: This is used to help take off some of the load of the server if there are many clients. Although the file is only being broadcasted once, there is a lot of handshaking that goes on at the start and end of the transmission to guarantee all data was delivered successfully. Depending on the different networks, their medium and reliability, a server may need some extra help with the handshaking if there are a lot of clients involved struggling to retrieve the data.

    Below shows an example of how the proxy can be utilized:
    A UFTP Proxy ConfigurationNote: Pinholes are used as a way to connect back to the UFTP Proxy Server effectively requiring no firewall changes to be made at each client site (only the server).

    **Note: It’s important to note a single Proxy Server can only be configured to connect to a single Proxy Client; it’s a 1 to 1 mapping. If you have multiple sites you need to connect to, you’ll need to set up an individual Proxy Server for each Proxy Client you need to serve.

    If you’re interested in the proxy portion of UFTP, you can read the official documentation about it found here.

Hand Over Everything

I wouldn’t have it any other way:

  • uftp-4.5.1-1.el6.nuxref.x86_64.rpm: The server is just the uftp tool and is really easy to use. This assumes you’ve got clients configured somewhere listening though!
    # just type uftp file.you.want.to.send
    uftp mytestfile
    
    # You can also send multiple files by just adding them to the end of
    # the string:
    uftp mytestfile1 mytestfile2 mytestfile3
    
    # I also wrote a small script that works the same way and sends stuff encrypted
    uftpe mytestfile1 mytestfile2 mytestfile3
    
  • uftp-client-4.5.1-1.el6.nuxref.x86_64.rpm: The client listens for data sent from the uftp server. You can use the RC Script i prepared to greatly simplify this tool:
    # as root; use the RC Script I wrote to make hosting the server
    # really easy
    service uftpd start
    

    Filtering is optional; if you don’t specify any, then by default there are no restrictions. Sometimes this is satisfactory (especially in closed or isolated networks). I attempted to simply UFTP’s built in server filtering for those who want to use it though. You see, not only can you encrypt the data you transmit from the server. But you can restrict the client to only accept connections from specific UFTP servers residing at a specific hosts with a specific server id. You can even go as far as only accepting servers with a specific fingerprint (created by their private key)

    # simply drop a configuration file in /etc/uftpd/servers.d 
    # Examples of accepted entries (taken from uftpd man page):
    # 0x11112222|192.168.1.101|66:1E:C9:1D:FC:99:DB:60:B0:1A:F0:8F:CA:F4:28:27:A6:BE:94:BC
    # 0x11113333|fe80::213:72ff:fed6:69ca
    #
    # You can have as many files as you want in this directory with as many entries in each
    # as you want.  If you add or remove new files, you'll need to restart the uftpd service
    # since it's only read in at the start.
    

    So by adding this bit of complexity, I know you are asking yourself:

    • Q: How do I know what my Server ID is?
      A: By default (using the rpm I’ve packaged) every server has an ID of 0x00000001 (decimal value of 1 – one) if you use the uftpe script I wrote (for encrypted transfers). To change your server id do the following:

      # Define a new id (other then 1)
      NEWID=2
      
      # Simply store this ID inside of the $HOME/.uftp config
      # file as it's HEX value:
      
      # Ensure the config directory exists
      [ ! -d $HOME/.uftp ] && mkdir -p  $HOME/.uftp
      
      # clear any old entry you may have set if you want:
      [ -f $HOME/.uftp/config ] && sed -i -e '/^UFTP_UID=/d' $HOME/.uftp/config
      
      # Set the new entry
      printf 'UFTP_UID=0x%.8xn' $NEWID >> $HOME/.uftp/config
      

      If however your just using the uftp tool on it’s own, it takes on the IP address of the host it’s running on (as it’s hex value) unless you explicitly specify -U 0x00000002 (or whatever ID you want it to assume). Here is a quick example of how you can convert an IP address to it’s hex value at the shell:

      # Define the address you want to convert
      IP_ADDR=192.168.1.128
      # Now convert it (don't forget the brackets!)
      (
         printf '0x'
         printf '%02X' $(echo "${IP_ADDR//./ }"); echo
      )
      # example above outputs: 0xC0A80180
      
    • Q: How do I know what my Server Fingerprint is?
      A: First off, uftp will not ever connect to this server with this option set if you choose ‘not’ to use the uftpe script i wrote or provide the necessary switches to enforce encryption. Setting a filter of your servers fingerprint is also a way of saying you only accept connections that are encrypted. This entry is completely optional. Your fingerprint ID is stored in $HOME/.uftp/uftp.key. Again this key only exists if your using the uftpe tool; otherwise the key is wherever you chose to store it. Fetch the id as follows (the below is intended to be called on the server where the uftp.key file exists):

      # fetch the details from the key:
      uftp_keymgt $HOME/.uftp/uftp.key
      

      Don’t panic if you don’t have a key; They are generated automatically when you first run the uftpe tool. The easiest way to pre-create it would just be to call uftpe by itself (without any parameters). Yes; it’ll spit an error telling you you didn’t provide it enough options. But the script will also generate you a key automatically too.

    I tried to think of everything; so log rotations and logging is already built in and included. You can locate them in /var/log/uftpd.log.

  • uftp-proxy-4.5.1-1.el6.nuxref.x86_64.rpm: the proxy service can bridge two networks that don’t support multicasting together. I haven’t spent to much time with this area since my environment hasn’t required me to. If you have any information to share about it; feel free and I can expand this area.
  • uftp-debuginfo-4.5.1-1.el6.nuxref.x86_64.rpm (Optional): This is only required if you are debugging this tool.
  • uftp-4.5.1-1.el6.nuxref.src.rpm (Optional): The source RPM for those interested in building the software for themselves.

Some Things To Consider:

When something is explained to be this easy, there is always a catch. I won’t lie, there are a few which means the UFTP solution may not be for everyone. They are as follows:

  • Multicasting isn’t enabled by most routers by default. If your recipients reside in a network you don’t manage, you’ll want to ask the local administrator to make sure their routers have (Level 2) multicasting enabled.
  • Multicasting can be a pain in the butt to troubleshoot; although newer routers won’t give you any grief, some of the older ones can fail to relay content correctly to clients who’ve also connected to the same multicast address. With negativity aside though, when it works, it works so great! My point is: you’ll need to make sure you’re using (networking) hardware that is relatively new (no older then 2010) where the firmware adequately supports Level 2 multicasting.
  • The UFTP Proxy attempts to resolve the problem of linking your networks together when separated by ones you don’t control. But consider that unless there are multiple recipients located on each network you connect your proxy too, you aren’t saving any bandwidth choosing this route.
  • Only uftp clients who are online will receive content sent by the uftp server. This can be a deal breaker for some especially if the product being delivered ‘MUST’ reach all of the clients. UFTP does not track who is online and who isn’t. It simply delivers content to those who are present at that time. It’s just like how you can’t watch a television show if you haven’t told your TV’s receiver what channel to be on.
  • If you’re using restrictive firewall settings (hopefully you are!), you’ll want to make sure multicasting is allowed into your client box with the following:
    iptables -A INPUT -m pkttype --pkt-type multicast -j ACCEPT

    It would be worth adding this to your /etc/sysconfig/iptables file as well.

Repository

Please note that all of these packages are also within my repository if that makes things easier for you and your deployment.

Sources

  • UFTP: Dennis Bush did a fantastic job with this tool. It is the key to making multicast file transmission powerful and reliable.
  • Multicasting: information in greater depth can be found here.

KeePassX – A Password Manager and Why You Need One

Introduction

I haven’t posted in a while and I figured I was due. I usually blog specifically for Linux users, but this really applies to anyone on any operating system (Apple, Microsoft, Android, etc).

I want to encourage the use of a password manager to anyone not already using one. There are a lot of them out there, but I’m specifically interested in focusing the attention on KeePassX. There are a number of reasons why and I’ll eventually get to most of them. But for starters KeePassX is completely free (GPLv2) and as I mentioned above, it works on just about every platform!

It’s sole purpose in life is to remember passwords for you so you don’t have to. It’s used to prevent you from using the same 1-3 passwords you’re using today for everything. Instead of using your birthday, engagement and/or pets name, you’ll use passwords like: JP83bW93wwrJsZ2x6tQy3aD6W or SLJUhoQWPBRtwTwmzsCxWXqOV. Again, I emphasis that the password manager does all the memorizing for you. Not only that, but it’ll easily generate you these passwords too.

KeePassX Interface

KeePassX Interface

Now before you roll your eyes and decide you don’t need such a thing, just here me out. Give me a chance to sell you the reasons why you seriously need to consider this. I’ll attempt to do this with respect to The 5 Stages of Loss and Grief. 🙂

Stage 1: Denial

What’s the point of a password manager? I never needed one before!
A password manager is kind of like social media was to us back in February of 2004. The ideology is the same: “You didn’t know you needed it until it was shown to you”. So trust me when I tell you that you need one now. The thing is, the internet is filled with people whose sole intent is to gain access to your identity and exploit it for their own personal gain. The passwords we’ve all used up to this date are too simple; I know this because we’ve all remembered/memorized them. Even the complicated ones we confidently memorized are no good.

Just Saying...

Food for Thought

Most of us just acknowledge there is risk, but we do nothing about it. We belive that if no one has figured out our password yet, they never will. Well the scary thing is: some of them might know our password(s) already. But these people don’t want to make that evident to us. Don’t expect someone to advertise themselves once they’ve gained access to something we had protected. Instead, you’re only going to find out once the damage has been done.

Stage 2: Anger

Why would I put all my passwords in one file? Something just sounds wrong with that statement.
You would do it for the same reason you trust a bank’s security with your money. The same reason you trust your wallet or purse with your personal identity. The same reason you go to work and secure all your belongings and pets behind in your home. We put all of our eggs into one basket every day, but we’re all smart about it. We all put trust in the decision that our belongings will remain in tact until we return to it. KeePassX works exactly the same way.

Both a Password and a Key File can be used to keep your password database safe.

Both a Password and a Key File can be used keep your password database safe.

The passwords that reside in your KeePassX database are encrypted, so no one will gain access to it unless you allow it to happen. The encryption means the password database is completely useless to anyone who has it without the keys required to access it. You can even go as far as to lock it using a keyfile (KeePassX will generate for you) as well as a password.

There is no question that if a hacker gains access to your password database and has all the keys he/she needs to unlock it, then you’ve defeated it’s purpose. Your passwords are only as secure as the conscious effort you take to keep them that way. If you keep the keys to your house under the welcome mat, or your car keys in the vehicle they pair with, it’s just a matter of time before you suffer a theft in that regard too.

Stage 3: Bargaining

Can’t I just change the passwords after I read about the compromising?
The answer is No and here is why:
People are attempting to exploit us ever day through phishing, viruses, spyware, false advertising, and even through everyday tasks we didn’t even know we were a victim of. Take Sony and eBay for example. Both are very reputable companies with an entire team of security experts working with them every day, yet they still fell prey when their systems were compromised by a hacker. As a result, it’s the clients and customers that become the victims too (all of us). If you used the same password on these sites as you do everywhere else, then you’re already at risk for identity theft. The point is, sh*t happens and sometimes it’s just out of our control.

We can’t expect every organization to be like eBay and Sony either. Not all of them will alert their customers of the threat they faced or the security breach they sustained. The few that do go public may have been exploited long before they did. Hence, our personal information was at risk last week when they told us today. There are even some companies who don’t want to admit to any privacy invasions to protect their own reputation. Then there are the companies that might not even know they’ve already been compromised. So if they don’t tell us; how will we ever know?

Therefore, consider taking the extra time to change every password on every site you visit once you get KeePassX installed.

Stage 4: Depression

I don’t want to change my password everywhere.
I don’t want the burden of a another application just to manage my passwords.
I was stuck at this stage for a while. It takes a while to change passwords everywhere. But after it’s done, you have to remember that this program does absolutely everything in its power to make your life easy from this point on. You only need to add everything once; so the burden doesn’t linger.

How can such complicated password make my life easier?

Ctrl+B and Ctrl+C are all you ever need to use once KeePassX is setup.

Ctrl+B and Ctrl+C are all you ever need to use once KeePassX is setup.

Your life ‘will’ be simpler with KeePassX because your every day tools are now accessible by just a few keystrokes:

  1. Press ctrl-b in Password Manager: Copy the username into the clipboard
  2. Press ctrl-v in Web Browser or App: Paste the username (into the username field)
  3. Press ctrl-c in Password Manager: Copy the password into the clipboard
  4. Press ctrl-v in Web Browser or App: Paste the password (into the password field)

That’s it; don’t worry about the password (you just copied) being left in the clipboard. KeePassX looks after clearing the clipboard after a few idle seconds elapse that you configure (the default is 20 seconds). The point of me explaining this is: instead of memorizing your secret passwords you use everywhere, you only need to remember the 4 key combinations identified above. The same 4 keystrokes are used for all sites/apps you ever use/visit from this point forward. Not to mention that each password is a unique from the other and unguessable by any hacker. I can’t stress enough that the effort level decreases with a password manager. At the same time your online privacy is more secure than ever.

Stage 5: Acceptance

What about my Phone? What about my other computer? Can access my password file on other systems?
Yes! This is one of the most amazing features of KeePassX! People even place their password file on locations such as DropBox or their Google Drive so they can access it between the systems. It’s compatible with Microsoft Windows, Mac OS (including Apple iOS), Android, and Linux (of course!).

So Where Do I Get It?

Microsoft Windows and Mac OS users can just download it directly from the download area at the official KeePassX website here.

If you’re using an Android device then you can find it here on the Google Play Store.

If you’re using an Apple device then you can find it here on the iTunes Store.

Linux users can download it from pkgs.org. It’s also available from the EPEL Repositories.

For the CentOS and/or Red Hat users: if for whatever reason the links above become unavailable or you want a fast approach: KeePassX can be retrieved from the repository I’m hosting.

Install KeePassX in CentOS and/or Red Hat 6 :

# Make sure you hook up with my repository first:
# Visit : http://nuxref.com/nuxref-repository/

################################################################
# Install our required products
################################################################
yum install -y --enablerepo=nuxref keepassx
# You're Done!

KeepassX Tips

KeePassX Password Generator

KeePassX Password Generator will keep your passwords diverse and complicated.

  • For obvious reasons, password protect your password database. This is the one password you ‘will’ need to remember. So I encourage you to use a new original one, but don’t forget it!
  • Consider using a keyfile as well as the password for securing your password database. The nice thing about the keyfile is you can move it with you; keep it on a usb drive that is kept with you or in another location. This way if someone ever did get a hold of your password database, they can’t do anything without the key file even if they know your password.
  • Configure KeyPassX to lock itself after it’s been idle or minimized. By default it won’t, but it’s a simple option that will allow you to walk away from your desk and know that no one is snooping where they shouldn’t be.
  • Log onto your remote sites and consider changing your passwords every now and then. Even if it’s only once a year. Just changing your passwords annually is still better than never changing them at all! You can optionally configure KeePassX to remind you to change your passwords after they get to a certain age. Just using the built in password generator will greatly simplify your life and keep your passwords complex.

Speaking of Passwords…

Consider that your neighbors (or even someone you don’t know) could be using your wireless network while you’re at work. They could be using it even when your around. Have you been connecting to your wireless router lately to see if you can account for everyone connected to it? Now would be a good time to change this password too!

Pay attention to the sites you use and make sure they use some form of login encryption. For example, logging into a website that isn’t secure means anyone can easily extract your username password combination without your knowledge.

Privacy Compromised

Just do a Google search for +breach +password +hacked to get an idea of how many companies are getting hacked constantly and how easy it is for someone to figure out your password and re-use it elsewhere.

Final Notes
Sure, Password Managers aren’t for everyone; don’t worry, I get that. But if you truly want to prepare yourself and prevent having to deal with unnecessary online fraud, or identity theft… If you truly wasn’t to avoid venturing through The 5 Stages of Loss and Grief which follows these awful crimes, then you should consider protecting yourself now. Take the plunge and get a password manager and diversify your passwords.

It’s better to be safe than sorry.

Credit

If you like what you see and wish to copy and paste this HOWTO, please reference back to this blog post at the very least. It’s really all I ask.

Sources

Here are some other links you may find useful:

Datetools: Date Manipulation and Cron Alternative For Linux

Introduction to Datetools

I wrote Datetools (in C++) to allow the manipulation of date time from the command line. It greatly simplified my life and maybe it will help yours out too!. It comprises of two core applications:

  • Dateblock: allows you to block until a scheduled period of time arrives unlike sleep which blocks for a set period of time. I found this so helpful, I ended up additionally building in an python extension for it.
  • Datemath: This application is just a simple way of preforming simple math on the system date.

The source code can be found here on GitHub if you’re interested in compiling it yourself. Or you can just scroll to the bottom of this blog where I provided the packaged goods.

Dateblock

The tool works very similarly to cron and sleep (a combination of the two); you can pass it a crontab string if that’s what you’re used too, or you can simply pass it in variables as arguments as well (as all other commands work):

Here’s is an example of what I mean:

# block until a minute divisible by 10 is reached:
# ex: HH:00, HH:10, HH:20, HH:30, HH:40, and HH:50
dateblock --minute=/10
# We will only reach this line when the above scheduled time has
# been met.
echo "Scheduled time reached; current time is: $(date)"

An equivalent crontab entry would look like this:

# block until a minute divisible by 10 is reached:
/10 * * * * echo "Scheduled time reached; current time is: $(date)"

Dateblock can also do another cool feature called ‘drifting’ which allows you to schedule processes on delayed cycles… Note that drifting is always specified in seconds. For example:

# Unblock on 5 minute cycles, but 2 minutes (120 seconds) into them:
# ex: HH:02, HH:07, HH:12, HH:17, HH:22, etc..
dateblock --minute=/5 --drift=120
# We will only reach this line when the above scheduled time has
# been met.
echo "Scheduled time reached; current time is: $(date)"

An equivalent crontab entry would look like this:

# block until a minute divisible by 10 is reached:
/5 * * * * sleep 120; echo "Scheduled time reached; current time is: $(date)"

The complexity of the tool can be as powerful as you want it to be:

# Unblock only on hours divisible by 5 on the 1st through to the 14th
# of every month (as well as the 20th). Unblock only when 30 seconds
# of that minute has elapsed.
 dateblock -o /5 -d 1-14,20 -s 30
# We will only reach this line when the above scheduled time has
# been met.
echo "Scheduled time reached; current time is: $(date)"

There is no way to reproduce this in a crontab unless the 30 second reference at the end is unnecessary… in that case:

# block until a minute divisible by 10 is reached:
0 /5 1-14,20 * * sleep 120; echo "Scheduled time reached; current time is: $(date)"

Just like crontabs, dateblock supports minute, hour, day of month, month and day of week. In addition, dateblock support seconds too. dateblock accepts traditional crontab entries as well as arguments:

#     day of week (0 - 6) (Sunday=0) --+
#     month (1 - 12) ---------------+  |
#     day of month (1 - 31) -----+  |  |
#     hour (0 - 23) ----------+  |  |  |
#     min (0 - 59) --------+  |  |  |  |
#  ***sec (0 - 59) -----+  |  |  |  |  |
#                       |  |  |  |  |  |
#                       -  -  -  -  -  -
# Dateblock Cron Entry: *  *  *  *  *  *
# Cron Crontab Entry:      *  *  *  *  *

# Unblock on the specific hours of 0 and 12:
# ex: HH:00, HH:12
$> dateblock --cron="0 0 00,12"

You’ll notice in the above, I didn’t bother specifying the remaining cron fields… In this case they will assume the default of *. But you can feel free to specify a * for readability. The other thing to observe is the addition of the second column which isn’t present in a regular crontab entry. It’s rules are no different then what you’ve already learned from other fields.

Testing

Simply adding a –test (-t) switch to your dateblock entry will allow you to test the tool in a debugging mode to which it will present to you the current time followed by when it would have unblocked for had you not provided the –test (-t) switch. It’s a great way to calculate when the next processing time will be.

Python Extension

To handle scheduled processes for my websites, I created a python extension for dateblock. This allowed to extend it’s flexibility with other offline processing… consider the following example:

from dateblock import dateblock
while True:
    # /5 as first argument means unblock on the 5th second of each minute
    dateblock('/5')
    print 'begin processing ...'
    # your code here...
    # if you want, you can even report the next unblock time
    print 'Done processing; blocking until %s' % 
        dateblock('/5', block=False).strftime('%Y-%m-%d %H:%M:%S')

You can also also access the drift as such:

from dateblock import dateblock
print 'Unblock at %s' % 
    dateblock('/5', drift=120, block=False).strftime('%Y-%m-%d %H:%M:%S')

Finally the python extension allows you to pass in a datetime object as an argument for calculating a time based on another (and not the current time which is the default).

from dateblock import dateblock
from datetime import datetime
from datetime import timedelta

# 31 days ago
reftime = datetime.now() - timedelta(days=31)

print('Would blocking until %s' % 
    dateblock('/5', drift=120, block=False, )
      .strftime('%Y-%m-%d %H:%M:%S') + 
    " if time was %s" % reftime
      .strftime('%Y-%m-%d %H:%M:%S'))

Things to Consider

Just like sleep, dateblock uses SIGALARM to manage its wake up time. Therefore if your code relies heavily on SIGALARM for another purposes, dateblock may not be a solution for you since you could interrupt it’s reliability (though not likely). This really shouldn’t be a big concern because this exact same warning comes with the sleep libraries we’ve been using for years. But it does mean that sleep could interfere with dateblock just as dateblock could interfere with sleep if they were both used in separate threads.

Dateblock vs Sleep

Dateblock vs Sleep

Why would I use dateblock over sleep?

Scheduling is the key… If your program relies completely on sleep, then the only thing you’re accomplishing is cpu throttling (controlling unnecessary thrashing). This is approach is fine if you’re going to just retry connecting to an unresponsive server in ?? seconds. But what if timing becomes an important factor of your application? The dateblock tool ensures you only unblock at absolute times vs sleep which unblocks at relative times with respect to when it was called.

Dateblock also allows your program to chronologically work in turn with other applications that may be on their own processing cycle. Such as something delivering data at the top of every hour. You may wish to have your program wake up 5 min after the top of each hour to perform the processing regardless of when your program was started.

Datemath

There isn’t as much to be said about Datemath; I personally never found a Linux/Unix tool that would allow me to script date/time calculations from the command line. For that reason, this tool exists.
Here is an example of the tools function:

# what time is it now?
date +'%Y-%m-%d %H-%M-%S'
# The above output was '2013-10-26 09-42-21' at the time of this blog
# what time will it be 5 months and 3 days from now
datemath --months=5 --days=3 --format='%Y-%m-%d %H-%M-%S'
# the above output was '2014-03-29 09-42-21' at the time of this blog
# and this makes sense... this is the calculation we want.

The tool supports negative values for calculating into the past as well and will handle leap years in the calculations too.

# what time is it now?
date +'%Y-%m-%d %H-%M-%S'
# The above output was '2013-10-26 09-45-45' at the time of this blog
# What was the current date 753 days ago?
datemath --days=-753 --format='%Y-%m-%d %H-%M-%S'
# the above output was '2011-10-04 09-45-45' at the time of this blog
# and this makes sense... this is the calculation we want.

No Python Module For Datemath

There is no python module for datemath because Python’s datetime and timedelta libraries already provide a fantastic solution for the same problem datemath solves…

# Simple code example to show why it really isn't
# necessary to port datemath to Python:
from datetime import datetime
from datetime import timedelta
in_the_past = datetime.now() - timedelta(minutes=15)
print '15 minutes ago: %s' % in_the_past
                              .strftime('%Y-%m-%d %H:%M:%S')

Just give me the goods

No problem, below are the RPMS as well as their accompanied source packages:

Package Download Description
dateblock
el6.rpm
/
el7.rpm
The powerful (cron like) command line interface (CLI) tool.
python-dateblock
el6.rpm
/
el7.rpm
The python extension for dateblock.
datemath
el6.rpm
/
el7.rpm
The datemath command line interface tool.
datetools
el6.rpm
/
el7.rpm
An optional package which includes licensing and information.

Note: The source rpm can be obtained here which builds everything you see in the table above. It’s not required for the application to run, but might be useful for developers or those who want to inspect how I put the package together.

No way, I’m building this myself; I don’t trust you

That’s okay, I understand; here is how you can build it yourself:

# Install 'mock' into your environment if you don't have it already
# This step will require you to be the superuser (root) in your native
# environment.
yum install -y mock

# Grant your normal every day user account access to the mock group
# This step will also require you to be the root user.
usermod -a -G mock YourNonRootUsername

At this point it’s safe to change from the ‘root‘ user back to the user account you granted the mock group privileges to in the step above. We won’t need the root user again until the end of this tutorial when we install our built RPM.

# Create an environment we can work in
mkdir datetool-build

# Change into our temporary working directory
cd datetool-build

curl -L --output datetools-0.8.1.tar.gz \
   https://github.com/caronc/datetools/archive/v0.8.1.tar.gz

# Extract Spec File
tar xfz datetools-0.8.1.tar.gz \
   datetools-0.8.1/datetools.spec \
      --strip-components=1

# Initialize Mock Environment
mock -v -r epel-6-x86_64 --init

# Now install our dependencies
mock -v -r epel-6-x86_64 --install boost-devel libstdc++-devel 
          glib-devel python-devel autoconf automake libtool

# Copy in our downloaded content:
mock -v -r epel-6-x86_64 --copyin datetools-0.8.1.tar.gz
   /builddir/build/SOURCES
mock -v -r epel-6-x86_64 --copyin datetools.spec 
   /builddir/build/SPECS

# Shell into our environment
mock -v -r epel-6-x86_64 --shell

# Change to our build directory
cd builddir/build

# Build our RPMS
rpmbuild -ba SPECS/datetools.spec

# we're now done with our mock environment for now; Press Ctrl-D to exit
# or simply type exit on the command line of our virtual environment
exit

Future Considerations

This is totally up in the air, at the moment the tool does everything I needed at the time. However I could see the following becoming a useful feature in the future:

  • Pass in a different time into both programs (instead of always working with the current time) (You can already do this with the dateblock python extension).
  • Have dateblock additionally take in a program and arguments as input to have it automatically execute the call to it when the scheduled time is reached. In addition to this, it means the dateblock tool would daemonize itself and run in the background on reoccurring schedules.
  • Add a devel package and create a shared library for C++ linking; perhaps the binary tools and extensions could link here too. Right now the library is just so small it’s really nothing to just include it statically as it is now.
  • Got an idea of your own? Pass it along! You can also submit a pull request to me on GitHub here.

Credit

Please note that this information took me several days to put together and test thoroughly. I may not blog often; but I want to re-assure the stability and testing I put into everything I intend share.

If you like what you see and wish to copy and paste this information, please reference back to this blog post at the very least. It’s really all I ask.