Skip to content

Linux

Introduction to cron

cron is a time-based job scheduler. This piece of software utility is used when you need to have a program run repeatedly at set time.

The daemon that runs in the background is named crond, while the file that contains the jobs themselves is named crontab.

You have three main directories:

  • /etc/crontab is the main system crontab file.
  • /var/spool/cron/ a directory for storing crontabs defined by users.
  • /etc/cron.d/ a directory for storing system crontabs.

Creating

Creating a crontab-file for your user is easy. Usage depends on what you need to do.

Edit

crontab -e

This command will allow you to edit the current user’s crontab. If a crontab doesn’t already exist, it will create a new one once you have saved your changes.

Edit another user’s crontab

crontab -u jorge -e

You can also edit another user’s crontab, but only if you have the correct permissions in place to do so.

List

crontab -l

or

crontab -u jorge -l

..to list another user’s crontab.

These are the most common usages of the command crontab. For a couple of more options, see man crontab.

Syntax

The syntax of a crontab-file looks like this:

* * * * * /path/to/program

Each asterisk represents a field. Starting from left to right, the fields are as follows:

  • Minute (0 – 59)
  • Hour (0 – 23)
  • Day of month (1 – 31)
  • Month (1 – 12)
  • Day of week (0 – 7, where 0 and 7 is Sunday)

On the fields Month and Day of the week, you can also use names instead of numeric values.

Operators

There are various operators that you can use with cron. Here’s the list:

Asterisk (*)

An asterisk (*) is used to indicate that every instance (i.e. every hour, every weekday, etc.) of the particular time period will be used. So if you use an asterisk in the field Hour, it means that it will run every hour.

Comma (,)

With this operator you can specify a list of values. If you use 1,5 in the field Day of week, this would mean Monday and Friday.

Dash (-)

While comma specifies a list of values, dash specifies a range. 1-5 in the field Day of week would mean Monday to Friday.

Forward slash (/)

Forward slash specifies a step value. If you’d like to execute a command every other hour, you could use 0-23/. You can also use steps after an asterisk, so if you want the command to run every two hours instead, use */2.

Examples

First

45 14 1 * * /home/jorge/backup.sh

In this example the script backup.sh runs at 14:45, the first day of the month, every month.

Second

30 04 1,15 * 5 /home/jorge/list_files.sh

This line runs the command list_files.sh at 04:30 on the 1st and 15th of each month, plus every Friday.

Third

00 08 * * 1-5 /home/jorge/wake_up.sh

The line above runs the command wake_up.sh at 08:00, Monday to Friday.

Fourth

*/5 * * * * * /home/jorge/annoy_wife.sh

..and this line would run the program annoy_wife.sh every five minutes, every day.

As always, if you want to know more about cron, check out the command man cron.

Have fun!

Split and merge PDFs – part 2

A while ago I wrote a post named Split and merge PDFs with pdftk. Unfortunately, pdftk seems no longer to be maintained for Fedora 21. So we have to use another alternative – poppler-utils:

Install the package with:

yum install poppler-utils

..and you can use them to both split and merge files. poppler-utils contains a list of tools that you can use to manipulate PDFs:

  • pdfdetach — lists or extracts embedded files (attachments)
  • pdffonts — font analyzer
  • pdfimages — image extractor
  • pdfinfo — document information
  • pdfseparate — page extraction tool
  • pdftocairo — pdf to png/jpeg/pdf/ps/eps/svg converter using cairo
  • pdftohtml — pdf to html converter
  • pdftoppm — pdf to ppm/png/jpeg image converter
  • pdftops — pdf to postscript (ps) converter
  • pdftotext — text extraction
  • pdfunite — document merging tool

So, we move on to merging and splitting:

Merge

pdfunite first_page.pdf second_page.pdf end_document.pdf

Split

pdfseparate -f 1 end_document.pdf %d.pdf

Check out man pdfseparate for more information about the tool.

Problems with wicd-curses on Fedora 20

If you’re on Fedora 20, are trying to run wicd-curses, and keep getting errors like the one below:

Traceback (most recent call last):
  File "/usr/share/wicd/curses/wicd-curses.py", line 1067, in 
    main()
  File "/usr/share/wicd/curses/wicd-curses.py", line 995, in main
    ui.run_wrapper(run)
  File "/usr/lib64/python2.7/site-packages/urwid/raw_display.py", line 241, in run_wrapper
    return fn()
  File "/usr/share/wicd/curses/wicd-curses.py", line 88, in wrapper
    return func(*args, **kargs)
  File "/usr/share/wicd/curses/wicd-curses.py", line 1003, in run
    app = appGUI()
  File "/usr/share/wicd/curses/wicd-curses.py", line 548, in __init__
    self.wiredCB = urwid.Filler(WiredComboBox(wiredL))
  File "/usr/share/wicd/curses/wicd-curses.py", line 378, in __init__
    self.__super.__init__(use_enter=False)
  File "/usr/share/wicd/curses/curses_misc.py", line 351, in __init__
    self.focus = focus
AttributeError: can't set attribute

..then the fix is simple. Open up the file /usr/share/wicd/curses/curses_misc.py, go to line 360, and paste the following below:

    @property
    def focus(self):
        return self._focus

    @focus.setter
    def focus(self, index):
        self._focus = index

    @focus.deleter
    def focus(self):
        del self._focus

    def set_list(self,list):
        self.list = list

wicd-curses should be working again. This is currently a bug on Bugzilla (https://bugzilla.redhat.com/show_bug.cgi?id=894646).

Introduction to strace

There will come a time when you will find yourself asking “What the heck is that process doing?”. To uncover the mysteries behind the behaviour of a process, we have a tool called strace.

The program strace is very handy when you want to debug the execution of a program. It catches and states all the system calls performed called by a process. It will also catch and state any inter-process signals received by this process.

Let’s dive into some examples.

Trace the execution

strace ls

..is the simple straight-forward way to use it. The output might look something like:

execve("/bin/ls", ["ls"], [/* 32 vars */]) = 0
brk(0)                                  = 0x1117000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fe7c5bc2000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=69243, ...}) = 0
mmap(NULL, 69243, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fe7c5bb1000
close(3)                                = 0
open("/lib64/libselinux.so.1", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\240d\0\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=142136, ...}) = 0
mmap(NULL, 2242712, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7fe7c5780000
mprotect(0x7fe7c57a1000, 2093056, PROT_NONE) = 0
...

The output looks a bit messy, but it can provide very useful information like which files does this program use, what is this program doing right now or why does this program not read the config file – does it even look for it?

Attach to an existing process

You can run strace on a process that’s already running. Use -p, and provide the Process ID (PID):

pidof urxvtd
772
strace -p 772

The output presented to you is similar to the example above. Notice that you can only trace a process you have access rights to. Multiple -p options will also trace these processes with a limit of 32 processes that strace can attach to.

Trace child processes

Use -f to trace child processes as they are created by currently traced processes. This is useful for debugging a program that spawns children. strace will prepend the pid of the traced process output:

strace -f ls

Trace specific system calls

strace -e open ls

The e-flag, along with the call open, displays only open system calls of the ls command, which outputs something along these lines:

...
open("/lib64/libdl.so.2", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libattr.so.1", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libpthread.so.0", O_RDONLY|O_CLOEXEC) = 3
open("/proc/filesystems", O_RDONLY)     = 3
open("/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3
ghost  ghost.zip
+++ exited with 0 +++

With the above example, close to the end, you can see two things – ghost and ghost.zip, a folder and file, which is the actual output of the command ls.

A few of the options available after -e trace= are:

  • open
  • close
  • read
  • write

Trace multiple system calls

What if you want to trace multiple system calls in one command though? The option -e trace= can take a comma separated set of systemcalls as argument:

strace -e trace=open,read ls

Which outputs:

...
open("/lib64/libattr.so.1", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\320\23\0\0\0\0\0\0"..., 832) = 832
open("/lib64/libpthread.so.0", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\340m\0\0\0\0\0\0"..., 832) = 832
open("/proc/filesystems", O_RDONLY)     = 3
read(3, "nodev\tsysfs\nnodev\trootfs\nnodev\tr"..., 1024) = 356
read(3, "", 1024)                       = 0
open("/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3
ghost  ghost.zip
+++ exited with 0 +++

Write output to file

If you’d like to write the output of strace to a file, add a -o:

strace -o ls.txt ls
ghost  ghost.zip

When you print the contents of ls.txt, you’ll see that it contains only the output from strace, and not from the command ls:

cat.ls.txt
...
write(1, "18.png\t\t   Apps  Declarations  d"..., 164) = 164
close(1)                                = 0
munmap(0x7f993acb6000, 4096)            = 0
close(2)                                = 0
exit_group(0)                           = ?
write(1, "18.png\t\t   Apps  Declarations  d"..., 164) = 164
close(1)                                = 0
munmap(0x7f993acb6000, 4096)            = 0
close(2)                                = 0
exit_group(0)                           = ?
+++ exited with 0 +++

Add a timestamp

If you add a -t to the command, you’ll be able to add a timestamp to each printed line. You can add up to 3 -t‘s. The more you add, the more verbose and detailed the timestamp will be.

One -t shows you seconds:

strace -t ls
...
11:52:20 close(2)                       = 0
11:52:20 exit_group(0)                  = ?
11:52:20 +++ exited with 0 +++

Adding a second -t will display microseconds:

strace -tt ls
...
11:53:07.593382 close(2)                = 0
11:53:07.593500 exit_group(0)           = ?
11:53:07.593651 +++ exited with 0 +++

A third -t will include the microseconds and the leading portion will be printed as the number of seconds since the epoch.

strace -ttt ls
...

If you’d like to find out the execution time of each call, -r will certainly do the trick:

strace -r ls
...
     0.000105 close(2)                  = 0
     0.000115 exit_group(0)             = ?
     0.000146 +++ exited with 0 +++

A summary of system calls

Would you like to have a summary of calls, time, and errors for each system call? -c does this:

strace -c ls
ghost  ghost.zip
% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
100.00    0.000054          11         5           mprotect
  0.00    0.000000           0         4           read
  0.00    0.000000           0         1           write
  0.00    0.000000           0         6           open
  0.00    0.000000           0         9           close
  0.00    0.000000           0         1           execve
  0.00    0.000000           0         1         1 access
  0.00    0.000000           0         3           brk
  0.00    0.000000           0         2           ioctl
  0.00    0.000000           0         2           munmap
  0.00    0.000000           0        15           mmap2
  0.00    0.000000           0         7           fstat64
  0.00    0.000000           0         2           getdents64
  0.00    0.000000           0         1           set_thread_area
  0.00    0.000000           0         1           openat
------ ----------- ----------- --------- --------- ----------------
100.00    0.000054                    60         1 total

This option is very useful when trying to find out why a program is running slow.

Introduction to lsof

Today I’m going to introduce you to the exciting world of lsof.

As you will see, it’s a nifty little tool that has various uses, and it has so many switches that you need both a and a + to use all the options available! As the description of the command says in its man-page:

lsof – list open files

So, let’s get started.

Network

List network connections

$ lsof -i
COMMAND    PID  USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
ssh        868 jorge    3u  IPv4  12710      0t0  TCP j-laptop.fbarr.lan:55908->login.redpill-linpro.com:ssh (ESTABLISHED)
chrome     967 jorge  114u  IPv4 372589      0t0  TCP j-laptop.fbarr.lan:44756->edge-star-ecmp-04-ams2.facebook.com:https (ESTABLISHED)
...

List TCP/UDP connections

$ lsof -i TCP
COMMAND    PID  USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
chrome     967 jorge  203u  IPv4 403952      0t0  TCP j-laptop.fbarr.lan:35942->173.192.82.194-static.reverse.softlayer.com:http (ESTABLISHED)
ssh        868 jorge    3u  IPv4  12710      0t0  TCP j-laptop.fbarr.lan:55908->login.acme.com:ssh (ESTABLISHED)

Simply replace TCP with UDP to see UDP connections.

$ lsof -i :22
COMMAND  PID  USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
ssh     1742 jorge    3u  IPv4 448777      0t0  TCP j-laptop.fbarr.lan:36484->j-desktop.fbarr.lan:22 (ESTABLISHED)
ssh     5409 jorge    3u  IPv4  73369      0t0  TCP j-laptop.fbarr.lan:45986->j-server.fbarr.lan:22 (ESTABLISHED)
$ lsof -i @192.168.1.1
COMMAND PID  USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
chrome  967 jorge  143u  IPv4 526978      0t0  TCP j-laptop.fbarr.lan:38571->calcifer.fbarr.lan:https (ESTABLISHED)

..and port:

$ lsof -i @192.168.1.1:443
chrome  967 jorge  143u  IPv4 526978      0t0  TCP j-laptop.fbarr.lan:38571->calcifer.fbarr.lan:https (ESTABLISHED)

It’s also possible to provide a port-range:

$ lsof -i :443-1000
COMMAND   PID  USER   FD   TYPE  DEVICE SIZE/OFF NODE NAME
chrome   4598 jorge   64u  IPv4   68058      0t0  TCP j-laptop.fbarr.lan:35515->do-20.lastpass.com:https (ESTABLISHED)
chrome   4598 jorge   98u  IPv6 5251212      0t0  TCP j-laptop.fbarr.lan:43729->lb-in-x5e.1e100.net:https (ESTABLISHED)

List connections with status LISTEN

$ sudo lsof -i | grep LISTEN
sshd      11903  root    3u  IPv4 549183      0t0  TCP *:ssh (LISTEN)
sshd      11903  root    4u  IPv6 549185      0t0  TCP *:ssh (LISTEN)

Replace LISTEN with ESTABLISHED, and various other options, to grab what you’re looking for.

List IPv4/IPv6 connections

$ lsof -i 4
COMMAND   PID  USER   FD   TYPE  DEVICE SIZE/OFF NODE NAME
chrome   4598 jorge   64u  IPv4   68058      0t0  TCP j-desktop.fbarr.lan:35515->do-20.lastpass.com:https (ESTABLISHED)
mutt    14654 jorge    3u  IPv4   41678      0t0  TCP j-desktop.fbarr.lan:57323->87.144.18.114:imaps (ESTABLISHED)

$ lsof -i 6
COMMAND   PID  USER   FD   TYPE  DEVICE SIZE/OFF NODE NAME
chrome   4598 jorge  127u  IPv6 5278504      0t0  TCP j-desktop.fbarr.lan:42348->lb-in-x5d.1e100.net:https (ESTABLISHED)
chrome   4598 jorge  182u  IPv6  132082      0t0  TCP j-desktop.fbarr.lan:59281->arn02s06-in-x0e.1e100.net:https (ESTABLISHED)

Users, processes and files

lsof not only is useful for network-related tasks, but works excellent for users, processes and files.

List open files of user

$ lsof -u jorge
...
COMMAND     PID  USER   FD      TYPE     DEVICE SIZE/OFF    NODE NAME
lsof      26305 jorge  txt       REG        8,3   146236  294089 /usr/bin/lsof
lsof      26305 jorge  mem       REG        8,3    46816  276251 /usr/lib/libnss_files-2.18.so
lsof      26305 jorge  mem       REG        8,3  1607632  294020 /usr/lib/locale/locale-archive
...

List processes by PID

$ lsof -n -p 25 -p 45

List processes by name

$ lsof -n -c urxvt
COMMAND  PID  USER   FD      TYPE             DEVICE SIZE/OFF    NODE NAME
urxvtd  1749 jorge  txt       REG                8,1  1299408 3431669 /usr/bin/urxvtd
urxvtd  1749 jorge  mem       REG                8,1    51808 3411196 /usr/lib/libnss_files-2.18.so

List connections to a file

$ sudo lsof /var/log/Xorg.0.log
COMMAND PID USER   FD   TYPE DEVICE SIZE/OFF    NODE NAME
X       400 root    0w   REG    8,1    30052 7602187 /var/log/Xorg.0.log

HUP a process

$ kill -HUP `lsof -t -c chrome`

Kill all of a user’s processes

$ kill -9 `lsof -t -u jorge`
$ lsof +L1

These files have been deleted, but one or several processes are keeping the files open. Though it might appear that the files are deleted from the filesystem, both the files and the blocks are being preserved.

These are just a few of the things you can do with lsof. I hope this tutorial has made you a little bit smarter!

urxvt and urlLauncher not working

I recently found myself having problems with urxvt. In my configuration-file, .Xdefaults, I had the following lines set up:

URxvt.perl-ext-common : default,matcher
URxvt.urlLauncher : /usr/bin/google-chrome

This would enable urxvt to highlight a link in white, and when clicking it would launch the URL in to a tab of my browser of choice. But one day it suddenly stopped working, for no apparent reason. After a little digging, I found the following in urxvt’s changelog, http://cvs.schmorp.de/rxvt-unicode/Changes:

– INCOMPATIBLE CHANGE: renamed urlLauncher resource to url-launcher.

Changing URxvt.urlLauncher to URxvt.url-launcher in .Xdefaults seemed to fix the problem!

Reducing PDF file-size in Linux

The other day I downloaded a PDF that ended up being a whole lot bigger than I thought. A “whopping” 230MB, which is another deal compared to the 30MB PDF’s that I’m accustomed to. So how to reduce the file-size? Ghostscript to the rescue!

If you have Ghostscript installed, run the following command to reduce the file-size of your PDF:

gs -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -dCompatibilityLevel=1.4 -dPDFSETTINGS=/screen -sOutputFile=new_file.pdf original_file.pdf

Now you have a few options here under -dPDFSettings:

  • /screen selects low-resolution output, and the lowest file-size.
  • /ebook selects medium-resolution output, with a medium file-size.
  • /printer and /prepress are both the high-resolution options, which is mainly used for printing PDFs. As you might have guessed, this option gives you the biggest file-size (yes, even bigger than your mother).

The results?

[jorge@(ashitaka):~/Downloads/PDF] du -h *
29M new_file.pdf
230M original_file.pdf

What can I say. I’m a cheap bastard when it comes to storage space, no matter how low the price might be. ;)

Vim re-edit file as root

Have you ever found yourself in a situation where you’ve edited a file for quite some time, only to find out that you get a “Permission Error” when trying to save the changes? If vim is your editor, and you have sudo-privileges, try doing this:

:w !sudo tee %

Does the trick. :)

BASH autocomplete for SSH

If you, like me, find yourself SSH’ing all day long, this little piece of code will do wonders. Well, it’ll save you some keystrokes at least. This line parses your .bash_history-file and tries to autocomplete the host you are trying to SSH to, given that you’ve already used SSH to access the host in question at least once before.

So, to make this work, place the following in your .bashrc or .bash_profile file:

complete -W "$(echo $(grep '^ssh ' .bash_history | sort -u | sed 's/^ssh //'))" ssh
source .bashrc

..to apply the change made to your .bashrc, if that’s the file you’ve made the change to. You should now be able to autocomplete hosts when SSH’ing with TAB.

Update: I am also (now) aware of, thanks to my colleagues, that you have to tweak and sometimes install additional packages to have a similar functionality provided by your system’s package manager. I find the solution above the easiest one, as it’s only a single line that needs to be included in a file, without any additional tweaks or packages necessary. But in the end, it’s your call!

P4 nettradio på Linux

Skulle du ønske å høre på P4 sin nettradio uten å måtte ha et nettleservindu åpen, kan du bare peke din mediaspiller (som f.eks. vlc eller mplayer) direkte til strømmen. Hvis vi bruker mplayer:

For P4:

mplayer mms://mms-cluster2.nextra.no/P4_Norge

For P4 Bandit

mplayer mms://mms-cluster2.nextra.no/P4_bandit

Bare erstatt mplayer med vlc, eller noe annet, skulle du ønske å endre mediaspiller som benyttes.