cron is the time-based task scheduler for Unix. I think the wikipedia article sums up its description best, so I won’t try and reproduce it:
Cron is the time-based job scheduler in Unix-like computer operating systems. Cron enables users to schedule jobs (commands or shell scripts) to run periodically at certain times or dates.
Today’s post will be a light tutorial in setting up jobs using cron.
Job types
Within the cron system there are two flavors of tasks. The first is at the system level the other is at the user level. The main difference being, the system level tasks (controlled by administrators) are able to run as any particular user. User jobs are setup by the user and installed for the user.
Job installation and modification
Start an editing session of the cron table (crontab) by issuing the following command.
$ crontab -e
You’ll now be looking at the job definitions that are setup. To add a job to the list, you need to add it in the following format.
Minute Hours Day Month DayOfWeek Command [args]
Minute is specified as (0 - 59)
Hours is specified as (0 - 23)
Day is specified as (0 - 31)
Month is specified as (0 - 12 where 12 is December)
DayOfWeek is specified as (0 - 7 where 7 or 0 are Sunday)
Command is the shell command you want to execute
For a system level task, a new field to specify the username is added into this format.
Minute Hours Day Month DayOfWeek Username Command [args]
This will only apply to system level tasks that are added. Operators can be used in conjunction with literal values to short-cut some of the more common tasks.
Use an asterisk * to define all values for a field
Use a comma , to separate multiple values for a field
Use a dash - to define a range
To make some more sense out of the time fields, here are a few examples and when they’d execute.
Crontab entry
Interval
0 1 * * * script.sh
Run at 1 in the morning everyday
0 6 1 * * script.sh
Run at 6am on the first of every month
0 11 * * 1-5 script.sh
Run at 11am every weekday
0 17 5 5 *
Run at 5 in the afternoon on the 5th of May
0 7-19/2 * * *
Run every 2 hours from 7 in the morning until 7 at night
Out of the box, a cron job will email your local unix account with the results of the job run. If you don’t want to receive this email just pipe the output of your cron command to null, like so.
0 7 * * * test.sh >/dev/null 2>&1
Some short-cut “special variables” that you can use in conjunction with the times that these jobs run look like this (these really clean up the way a crontab reads).
Variable
Meaning
Cron equiv.
@reboot
Run once, at startup
@yearly / @annually
Run once per year
0 0 1 1 *
@monthly
Run once per month
0 0 1 * *
@weekly
Run once per week
0 0 * * 0
@daily / @midnight
Run once per day
0 0 * * *
@hourly
Run once per hour
0 * * * *
Other maintenance
You can list the cron table with the following command.
$ crontab -l$ crontab -u user -l
You can remove all entries out of the cron table with the following command.
Seeing so many “Hello, world” concepts for getting up an running in Assembly has annoyed me a little bit. I see people using the $ - msg macro to calculate the length of their string at assemble time. In today’s post, I’ll show you how to measure the length of your string at runtime so you’ll be able to provide the write syscall’s third parameter a little more flexibly.
The logic
The logic behind this procedure is dead-simple. Test the current byte for being null, if it is get out now if its not keep counting! Here’s how the code looks.
_strlen:pushrcx; save and clear out counterxorrcx,rcx_strlen_next:cmp[rdi],byte0; null byte yet?jz_strlen_null; yes, get outincrcx; char is ok, count itincrdi; move to next charjmp_strlen_next; process again_strlen_null:movrax,rcx; rcx = the length (put in rax)poprcx; restore rcxret; get out
This is just straight-forward memory testing, no great advancements in computer science here! The function expects that the string that requires testing will be in the rdi register. To actually use this function in your application though, you’ll need to transport the result (which sits in rax by the time the function has completed execution) into the register that write expects its length parameter. Here’s how you use your new strlen function (in the Debian scenario).
; strlen(hello)movrdi,hello; rdi is the string we want to ; get the length ofcall_strlen; get the length!movrdx,rax; rdx now holds the string length; ready for our write syscall; write(fd, buf, len)movrax,4; syscall 4 == writemovrbx,1; fd = 1 == stdoutmovrcx,hello; the string to writeint0x80; print the string
So you can see that this is quite straight forward. We setup rdx before we setup the rest of the registers. We could have done this the other way around - to be on the safe side, I’ve done it this way as you never know what registers get mowed over in people’s functions. I tried to help this also in the _strlen implementation by saving the only work register that I use rcx. Anyway, that’s how you measure your string.
A more optimal way?
After completing this article, I’d thought about the “brute-forcish” way that I’d crunched out the numbers to derive a string’s length and thought to myself, what if I could just scan the string of bytes - find the null character and subtract this found index from the original starting point. Mathematically I would have calculated the distance in bytes between the start of the string and the NULL character, ergo the string length. So, I’ve written a new string length implementation that does just this and here it is.
_strlen2:pushrbx; save any registers that pushrcx; we will trash in heremovrbx,rdi; rbx = rdixoral,al; the byte that the scan will; compare to is zeromovrcx,0xffffffff; the maximum number of bytes; i'm assuming any string will; have is 4gbrepnescasb; while [rdi] != al, keep scanningsubrdi,rbx; length = dist2 - dist1movrax,rdi; rax now holds our lengthpoprcx; restore the saved registerspoprbxret; all done!
It may look longer than the first implementation however this second implementation uses SCASB which will be heaps more optimal than my hand-rolled loop.
Putting some of the knowledge we’ve picked up in this previous post, today’ss post is going to be about getting the value that sits in a register out on screen. This post will assume that we’re not going to lean on a call like printf, we’re going to do it by hand.
How to attack the problem?
The solution that I present may immediately strike your eye as verbose & long-winded and this is on purpose. We’re going to build something that works to begin with then we can do an analysis of what we’ve written and optimise it later. I’ve split the larger problem of printing a register’s value (in this case we’re printing RAX) into a few smaller problems so as we knock off each problem, we get closer to an overall result. The sub-problems that I have cut this into are:
Printing a nibble (half a byte or 4bit value)
Printing a byte
Printing the register value
So you can see that we’re going to implement a solution by solving these smaller issues top to bottom. Let’s take a look at some code.
Characters and Nibbles
We’re going to print a nibble. A nibble is 4 bits of data spanning values from 0 up to F hexadecimal or 0 up to 15 in decimal. The plan of attack is to isolate this 4 bits in such a way that we can use it as an offset into a string of characters organised from 0 up to F. Here’s the code.
section.datahex_charsdb"0123456789ABCDEF"; our hex char lookup stringsection.text; it's assumed that the lower 4 bits of al contains; the nibble that we want to print. rax really needs; to be zeroed out elsewhere for this to work_print_nibble:pushrsi; save off any of the register that pushrax; we know that we'll destroy in thispushrdi; procedurepushrdxmovrsi,hex_chars; load the base addressaddrsi,rax; offset the base address by the value; we want to print, therefore indexing; the charactermovrax,0x2000004; write() syscallmovrdi,1; write out to stdoutmovrdx,1; write 1 byte!syscall; make the callpoprdx; restore all of the registers thatpoprdi; we saved at the startpopraxpoprsiret; get out
The code is documented pretty well, and you can see that the crux of the work is just offsetting the base address of the string by the nibble that we want to print. Nifty. Keep in mind that the registers used here are assuming that you’re compiling for OSX. If you are compiling for another type of unix make sure that the parameters are being passed through the correct registers, otherwise you’ll be segfaulting all the way to the pub!
Stepping up to a byte
Now we want to chain two _print_nibble calls together so that we can print an entire byte out on the screen (0 up to FF). We’ve already got a procedure that prints the lower 4 bits of al out to the screen, all we really need to do is be creative with al so we can print the higher 4 bits first then the lower 4 bits so that the number comes out to the console in the right order! Here’s the code.
_print_al:pushrbx; we know that rbx will get a touch; up here, so save it offmovbl,al; take a copy of the whole byte and shral,4; move the top 4 bits into the lower; 4 bits of al ready for printingcall_print_nibble; print the lower 4 bits of al moval,bl; restore al again andal,0xf; isolate the lower 4 bits of alcall_print_nibble; print the lower 4 bits of al poprbx; restore rbxret; get out
This function holds the same assumption as printing a nibble. There can’t be any junk in the higher bits (from al) of rax otherwise this solution will turn to mud.
Going the whole hog!
We’re now able to print any byte we would like, so lets string 8 bytes together to make a 64bit integer that we can print. Again, it’s all about shuffling the value that we want to print around correctly so that the number is written to the console in the correct order. It might be confusing to see pushes and pops inside of the loop that I’ll present, but I re-use these registers to calculate things on the fly. Again, I’ve commented this code pretty verbosely so it should read like a bedtime story. Here’s the code.
_print_rax:movrcx,8; there are 8 bytes to print _next_byte:pushrax; store off the value to printpushrcx; store off the byte countdecrcx; make rcx zero basedshlrcx,3; transform rcx so that it will; hold the number bits that we; shift out value by so we can; isolate the correct byteshrrax,cl; isolate the correct byte in al andrax,0xff; make sure there is nothing in ; the upper parts of raxcall_print_al; print the value in alpoprcx; restore the counter poprax; restore the value we're printingdecrcx; move onto the next bytejnz_next_byte; process the next byte if we ; haven't yet finishedret; get out!
The key is byte isolation. Using rcx we can count from the top byte down to the bottom with creative shifting. Now that we’ve implemented all of this code, we can print some boobies to the screen. This is the moment you’ve been waiting for.
_start:movrax,0xb000b135b000b135; the value to print call_print_rax; print them to screenmovrax,0x2000001; exit syscallmovrdi,0syscall
The output of which should just print “B000B135B000B135” to the console. Yes, there’s boobies in the article, see! Whilst this may not appear to be the most useful function right now, it’ll serve as a very useful debugging tool for us in the future.
Here’s a quick little ruby snippet to get you sending email through your gmail account. I had to implement this recently, so I thought I’d make note of it here. You will need the tlsmail gem installed to make this happen. Here’s the code.
require'tlsmail'require'time'from="me@email.com"to="someone@email.com"pwd="SECRET PASSWORD"content=<<EOF
From: #{from}
To: #{to}
MIME-Version: 1.0
Content-type: text/html
Subject: An email for you
Date: #{Time.now.rfc2822}
<p>Hello to you!</p>
EOF # start up a TLS session (required by GMail)Net::SMTP.enable_tls(OpenSSL::SSL::VERIFY_NONE)# send the emailNet::SMTP.start('smtp.gmail.com',587,'gmail.com',from,pwd,:login)do|smtp|smtp.send_message(content,from,to)end