Linux for Newbie(Part 4.3)
3 Job scheduling with "at", "batch", and cron
3.1 How do I execute a command at specified time (using "at" or "batch")?
The at command will execute the command(s) you specify at the date and time of your choice. For example, I could start playing music from my CDROM at 7 o’clock in the morning:at 7:00
cdplay<Ctrl>d
In the example above, I entered the first line "at 7:00" on the command line and then pressed ENTER. To this, the at command displayed a prompt "at>". At this prompt, I entered my command "cdplay" and then pressed the control key and "d" simultaneously to finish the input. If instead of pressing <Ctrl>d , I pressed "ENTER", the next "at>" prompt would appear, at which I would be able to enter the next command to be executed right after "cdplay", also at 7:00. And so on, I could have had many commands scheduled for execution one by one starting at 7:00. After typing the last command, I would finish the input with <Ctrl>d. Think of the <Ctrl>d as sending "end-of-file" to the current input. Don’t press <Ctrl>d twice because this will log you out--that’s what <Ctrl>d does when entered straight on the Linux command line.
You can list the job you scheduled for execution using:
at -l
which will give you the numbered list of the jobs waiting.
If you changed your mind, you can remove a job from this list. For example:
atrm 8
will remove the job with the number eight on the list.
I could also schedule a job for execution much later, for example:
at 23:55 12/31/00
startx
would start my X-windowing system right on time for the new millennium (5 minutes before midnight on 31 of December 2000).
If you cannot execute the at command, check if the at daemon ("atd") is loaded (as root, use setup-"system services"). If you cannot execute the at command as a regular user although it works for root, check if the empty file /etc/at.deny exists and there is no file /etc/at.allow. This should be the default setup and it permits all the users to execute at. If you want only certain users to use at, create a file /etc/at.allow and list these users there.
For other options, check:
man at
If you wish to perform a processor-intensive job in a background when the system load is low, you may choose to use the batch command. For example, I could run setiathome (a program cranching data to help in search of extraterrestial intelligence, SETI) using:
batch
at>setiathome<Ctrl>d
In this example, I entered the command batch and then, at the "at>" prompt, I entered the command which I wanted to be executed in the background. The job tries to start immediately, but goes ahead only when the system load is under 0.8 You can check the system load by inspecting the contents of the (virtual) file /proc/loadavg . For example:
cat /proc/loadavg When a batch job finishes, the output is sent to me via e-mail.
3.2 How do I set up cron?
Cron (a Linux process that performs background work, often at night) is set up by default on your RedHat system. So you don’t have to do anything about it unless you would like to add some tasks to be performed on your system on a regular basis or change the time at which cron performs its duties.Please note that some of the cron work might be essential for your system functioning properly over a long period of time. Among other things cron may:
- rebuild the database of files which is used when you search for files with the locate command,
- clean the /tmp directory,
- rebuilding the manual pages,
- "rotate" the log files, i.e. discard the oldest log files, rename the intermediate logs, and create new logs,
- perform some other checkups, e.g. adding fonts that you recently copied to your system.
Therefore, it may not be the best idea to always switch your Linux machine off for the night--in such a case cron will never have a chance to do its job. If you do like switching off your computer for nights, you may want to adjust cron so it performs its duties at some other time.
To find out when cron wakes up to perform its duties, have a look at the file /etc/crontab, for example:
cat /etc/crontab
It may contain something like this:
# run-parts
01 * * * * root run-parts /etc/cron.hourly
02 4 * * * root run-parts /etc/cron.daily
22 4 * * 0 root run-parts /etc/cron.weekly
42 4 1 * * root run-parts /etc/cron.monthly
You can see that there are four categories of cron jobs: performed hourly, daily, weekly and monthly. You can modify those or add your own category. Here is how it works.
The columns in the entries show: minute (0-59), hour (0-23), day of month (1-31), month of year (1-12), day of week (0-6--Sunday to Saturday). The "*" means "any valid value".
Thus, in the example quoted, the hourly jobs are performed every time the computer clock shows "and one minute", which happens every hour, at one minute past the hour. The daily jobs are performed every time the clock shows 2 minutes past 4 o’clock, which happens once a day. The weekly jobs are performed at 22 minutes past four o’clock in the morning on Sundays. The monthly jobs are performed 42 minutes past four o’clock on the first day of every month. The directory with the script file that contain the command(s) to be executed is shown as the last entry on each line.
If you wanted your jobs to be performed at noon instead of 4 in the morning, just change the 4s to 12s. Cron wakes up every minute and examines if the /etc/crontab has changed so there is no need to re-start anything after you make your changes.
If you wanted to add a job to your cron, place a script which runs your job (or a link to your script) in the directory /etc/cron.hourly or cron.daily or /etc/cron.weekly, or/etc/cron.monthly.
3.3 Swap space
Swap is an extension of the physical memory of the computer. Most likely, you created a swap partition during the initial RedHat setup. You can verify the amount of swap space available on your system using:cat /proc/meminfo
The general recommmendation is that one should have: at least 4 MB swap space, at least 32 MB total (physical+swap) memory for a system running command-line-only, at least 64 MB of total (physical+swap) memory for a system running X-windows, and swap space at least 1.5 times the amount of the physical memory on the system.
If this is too complicated, you might want to have a swap twice as large as your physical (silicon) memory, but not less than 64 MB.
If you ever need to change your swap, here are some basics.
3.4a Swap partitions
You can have several swap partitions, each up to approximately 124 MB. Here are the steps to create and enable a swap partition:- Create the partition of the proper size using fdisk (partition type 82, "Linux swap").
- Format the partition checking for bad blocks, for example:
mkswap -c /dev/hda4
You have to substitute /dev/hda4 with your partition name. Since I did not specify the partition size, it will be automatically detected.
- Enable the swap, for example:
swapon /dev/hda4
To have the swap enabled automatically at bootup, you have to include the appropriate entry into your /etc/fstab file, for example:
/dev/hda4 swap swap defaults 0 0
If you ever need to disable the swap, you can do it with:
swapoff /dev/hda4
3.4b Swap files
Swapping to files is usually slower than swapping to a raw partition, so this is not the recommended permanent swapping technique. Creating a swap file, however, can be a quick fix if you temporarily need more swap space. You can have up to 8 swap files, each with size of up to 16 MB. Here are the steps for making a swap file:- Create a file with the size of your swap file:
dd if=/dev/zero of=/swapfile bs=1024 count=8192
This physically creates the swap file /swapfile, the block size is 1024 B, it contains 8192 blocks, the total size is about 8 MB. (The dd command copies files. In the example above, the input file (if) was /dev/zero, the output file (of) was /swapfile. You cannot use the cp (copy) command for creating a swap file because the swap file must be physically continuous on the hard drive.)
- Set up the file with the command:
mkswap /swapfile 8192
- Force writing the buffer cache to disk by issuing the command: sync
- Enable the swap with the command:
swapon /swapfile
When you are done using the swap file, you can turn it off and remove:
swapoff /swapfile rm /swapfile
You may also want to see the nice info written by Linus Torvalds himself: man mkswap
3.5a Shell
3.5b What is a shell and do I want to use a different one?
A shell is the program that interprets what you type on the command line and decides what to do with it. A shell can also be invoked in a non-interactive way, for example to execute a pre-typed list of commands contained in a text file (a "shell script"). Think of a shell as an equivalent of the DOS "command.com" (command-line interpreter) and the shell script files as an equivalent of the DOS batch files (*.bat).There are several shells available on the Linux system (if you installed them): bash ("Bourne Again" shell), sh (Bourne shell), csh (C shell, with a syntax akin to the "c" programming language), pdksh (public domain Korn shell), tcsh (enhanced C shell), ash, zsh, and perhaps a couple more.
The default shell on my system (and most probably on yours too) is bash , which is an excellent and standard shell, and I really cannot see a reason why a newbie like myself would want to change it. bash is fully backwards-compatibile with the Bourne shell (the most popular shell on UNIX) and incorporates many enhancements and best features from other shells. From a newbie prospective, the different shells are included with Linux for historical reasons and backwards-compatibility of shell scripts that may require a particular shell to run.
If you wanted to try another shell, type, for example
tcsh
which will start the enhanced c shell. When done, type
exit
which will return you to the previous shell.
The shell for each user is specified as the last field in the in the password file /etc/passwd . If you really wanted to change it, edit (as root) this file and replace the "/bin/bash" with the shell of your choice.
3.5c How do I write a simple shell script?
Create a text (ASCII) file that is to contain the shell script. For example, I would use the pico editor to write a script that runs the program tar with all the parameters usually necessary to uncompress a tarball downloaded from the Internet (I never seem to remember the tar options). I decided to call my script "untar":pico untar
Since the file "untar" did not exist in my current directory, it was created by the pico text editor. Now, I type in the content of my script:
#!/bin/bash
echo this is the script file $0
echo untarring the file $1
# this calls tar with options -xvzf (extract, verbose, filter through gzip, input filename)
tar -xvzf $1
I save the file with <Ctrl>o and exit with <Ctrl>x
The first line of the script, starting with "#!" (called pound-bang), is special--it tells the shell what program should be used to interpret the script. In this example, the script is to be interpreted by the bash shell /bin/bash . The first line must start with #! or the script will never run (the file will be interpreted as just a text file). Other lines starting with # are comments for the author (readers, users) of the shell and are totally ignored by the computer.
The $0, $1, $2 ... in my script are the parameters passed to my script. For example, if I ran a script called "myscript" with seven parameters like this:
myscript a b c d e f g
then $0 would be seen inside "myscript" as having the value "myscript", $1 would have the value "a", $2 would be "b", $3 would be "c", etc.
On the second and third line of my example script, the command echo prints on the screen everything that follows on the same line, expanding $0 and $1 to the values of the parameters passed to the script. The fourth line is a comment written to myself to remaind me what I was trying to achieve, just in case I ever had to modify my script. The fifth line performs the actual work. Once the script is written, I make the text file executable to the file owner:
chmod u+x untar
and my script is ready to use:
./untar my_tar.tar.gz
Linux scripting is definitely rich, flexible, powerful and can be complex. However, it does not require special knowledge to write simple scripts for automation of common tasks. You just put togheter a group of often used commands, one by one, into a file. I use scripting because I am too lazy to type the same groups of commands over and over again.
3.6a Simple programming
3.6b How do I write a simple Python program?
Quite like writing a shell script. Create/edit a text file that will contain your Python program:pico try_python
Type in some simple python code to see if it works:
#!/usr/bin/env python
print 2+2
The first line tells the shell how to execute this text file. The second is a simple python expression.
After saving the file, I make it executable:
chmod a+x try_python
after which I can run it by typing:
./try_python
Python is an excellent, and very modern programming language, so give it a try. Very good (and large) free handbooks by G. van Rossum (the Python creator) are available on the net (try:http://www.python.org/doc/ for browsing or ftp://ftp.python.org for downloading).
3.6c How do I write a simple GUI program (using Tk)?
Tk is a GUI extension of the easy yet powerful tcl programming language. For example, I may use pico to create a text file that will contain a simple tk program:pico try_tk
and type in a simple example of tk code to see if it works:
#!/usr/bin/wish
button .my_button -text "Hello World" -command exit pack .my_button
The first line (starting with the "#!" pound-bang) tells the shell what utility to use to execute my text file. The next two lines are an example of a simple tk program. First, I created a button called "my_button" and placed it at the root of my class hierarchy (the dot in front of "my_button"). To the button, I tied the text "Hello World" and a command that exists the program (when the button is pressed). Last line makes my program’s window adjust its size to just big enough to contain my button.
After saving the file, I make it executable: chmod a+x try_tk
after which I can run it by typing (in the X-terminal, because it requires X-windows to run):
./try_tk Tk is a very popular for building GUI front ends.
3.6d How do I write a simple perl script?
Perl is a scripting language famous for its power, flexibility and perhaps cryptic syntax. It is also very popular amoung linux and unix (and not only) gurus. I may use pico (or any other text editor of my choice) to create a simple perl script. The script below does nothing useful, yet illustrates some features of perl:#!/usr/bin/perl -w
#sample perl program
# name of scalar variables start with $
$a=2;
$b=3;
print $a**$b,"\n";
$hello_world=’Hello World’;
print $hello_world,"\n";
system "ls";
The first line tells the shell how to execute my text file. The option "-w" causes perl to print some additional warnings, etc. that may be useful for debugging. The next two lines (starting with #) are comments. The following lines are almost self explanatory: I assign some values to two variables ($a and $b), put $a to power $b and print the result. The "\n" prints a new line, just like in the "c" programming language. Then I define another variable to contain the string "Hello World" and, in the next line, I print it to the screen. Finally, I execute the local operating system command "ls", which on Linux prints the listing of the current directory content. Really stupid script. Surely, I must remember to save the file, then make it executable (see the previous answers) and then I am ready to run it.
3.6 How do I compile a simple C program?
Start your favourite text editor and type in your source code. For example, I may use pico:pico hello.c
and type in the Kerningham and Richie (the creators of "c") intro example of a C program:
#include <stdio.h>
void main(void) {
printf("hello world\n");
}
I save the file and then envoke the GNU C complier to compile the file "hello.c":
gcc hello.c
The gcc complier produces an executable binary file "a.out", which I can run:
./a.out
3.7 How do I install a program I downloaded from the Internet?
o If the program is a RedHat binary package (*.rpm), I use the RedHat package manager rpm . First I read the info on the package content:rpm -qpi my_new_file.rpm
This queries (mode "q", must be the first letter after the dash) the yet uninstalled package (option "p") so that it displays the info (option "i") which the package contains. If I want to install the program, I run (as root):
rpm -ihv my_new_file.rpm
This runs rpm telling it to install the package (mode "i", must be the first letter after the dash) while printing to the screen more information than usual (option "h"=display "hashes" to show the unpacking progress, option "v" = be verbose). The contents of the package is distributed to the directories where it belongs. After this installation, the program is ready to run, I just have to find where the executable is. If I have trouble finding the executable, this lists all the files that the package contains together with their destination directories:
rpm -qpl my_new_file.rpm
This queries (option "q") the yet uninstalled package (option"p) so that it displays the listing (option "l") of all the files the package contains.
There are also GUI front-ends to rpm: glint (very slow, comes with RH5.2), gnopro (confusing, comes with RH6.0), and kpackage (by far the best of the three but it has to be installed separately--check your favorite Linux software site to download it).
o If what you downloaded from the net is a Linux source code in a form of a compressed tarball, the procedure is longer than with the binary-only rpm. I typically install the program as root.
First, I change my current working directory to /usr/local :
cd /usr/local
Second, I decompress the tarball that I downloaded from the net:
tar -xvzf
/home/the_directory_where_the_tarball_is/my_tarball.tar.gz
This extracts (option "x") the contents of the *.tar.gz (or *.tgz) tarball , unzips it (option "z") while talking to me more than usual (option "v" = verbose). Please note that the option "f" means "file", so the filename must immediately follow the letter "f". The contents of the tarball is extracted into a subdirectory which tar creates under my current working directory, which in this case is /usr/local/ . The tarball knows what the new subdirectory should be called.
If the tarball is not compressed, I may use:
tar -xvf /home/the_directory_where_the_tarball_is/my_tarball.tar
Third, I have a look if the new subdirectory was created and how it is called, then I cd into it:
cd the_new_program_subdir
Since some of the directories have long names, I use the great autocompletion option to save on typing--I just type the first few letters and then press <TAB> .
Fourth, most programs are compiled by executing these three commands:
./configure make
make install
The above commands can take some time to complete (0.5 h?). If any of them fail, it might be an idea to read the README or INSTALL or whatever info is provided with the new program. Some programs may require customization of the environment (e.g. addition of their directory to the PATH) or installation of an additional library, or yet something else. It can sometimes be a pain. Very simple programs might not need the "./configure" or/and "make install" step, in which case "make" alone will do.
Fifth, if everything goes well, I find the executable in the new program. The names of executables display in green when running this command:
ls --color
Now, I can run the executable:
./the_executable
Sixth, if I plan to run the program more often, I create a symbolic link to the executable from the directory /usr/local/bin :
cd /usr/local/bin
ln -s /usr/local/the_new_program_subdir/the_executable .
This way, the executable (actually, a symbolic link to it) is on my PATH and it can be run by simply typing its name (no need to type the full path to the executable any more). Some programs will put the executable (or a link to it) in a bin directory so you can skip the last step.
o There are also programs distributed as "source code rpm" packages. They require installation of the *.rpm package with the "rpm" utility and then compliation of the source code by executing the same: "./configure - make - make install" sequence as for the sourcecode distributed as tarballs.