Skip to navigation

Running X apps (like zenity) from crontab (solving “cannot open display” problem)

January 2nd, 2009

I’ve written a small script that checks whether I have queued mail and that displays a notification icon via “zenity –notification” in case I do. I wanted to run it using ~/.crontab but it wouldn’t run. First, I got error messages from the cron daemon that looked like this:

(zenity:22981): Gtk-WARNING **: cannot open display:

Sure, I hadn’t specified a display. So I tried setting the DISPLAY explicitly in my ~/.crontab:

* * * * export DISPLAY=:0.0 && /path/to/checklog

but then I got:

No protocol specified

(zenity:24101): Gtk-WARNING **: cannot open display: :0

The same happened when I tried running other X apps, like audacious. A line in ~/.crontab like this:

* * * * * DISPLAY=:0 /usr/bin/audacious

resulted in errors like this:

No protocol specified
/usr/bin/audacious: Unable to open display, exiting.

It turns out I needed to set, in my ~/.bashrc:

xhost local:mpromber > /dev/null

to allow crontab access to my X display. It now works, either using “export DISPLAY=:0.0” in the ~/.crontab, or alternatively just using

zenity --notification --display=:0.0

in the script that checks for queued mail.

Ubuntu/ Linux: How to permanently turn off the annoying system bell (beep)

December 4th, 2008

You know what I mean … that loud loud beep that almost knocks you out whenever you type a non-available keyboard shortcut in Emacs.

For immediate relief (this will not persist through a reboot):

sudo modprobe -r pcspkr

For permanent relief, edit the file /etc/modprobe.d/blacklist and add the line:

blacklist pcspkr

Addendum

On my Lenovo Thinkpad X41, there was still an annoying loud beep whenever I plugged in or unplugged the AC power cord. I had to disable this in the BIOS.

“trash-cli” lets you move files to the trash from the command line (and shell scripts)

November 28th, 2008

I know hardcore Linuxers use rm for everything and think the trash on a computer is for babies who also like such poo-poo things like the mouse and GUIs. However, I’ve just deleted one too many files using rm from a shell script, especially since I like doing rm -rf on directories … confirming every single file is just too tedious. So I googled some and found the best of both worlds: trash-cli lets you move items to the trash can from the command line or shell scripts. You use it simply like so:

trash somefile

Unlike just moving files to wherever you trash folder is using mv, trash-cli does all the nice trashy things like keeping information that will let you easily restore the file (which … ahem … you of course do from the trash can GUI). On Ubuntu, it’s easy to get trash-cli via synaptic:

sudo aptitude install trash-cli

Now, if there only were a way to rename the trash can to “trash” or at least “rubbish” instead of the idiotic “wastebasket” that my Xubuntu with GB locale insists on …

How to add a custom welcome message to your Xubuntu or Ubuntu login screen

November 28th, 2008

I like the graphical login screen on my laptop to display my e-mail address. In case I lose the laptop and an honest person finds it, they should at least have the possibility to return it.

In the latest versions of Ubuntu or Xubuntu, you can change the welcome message via the settings menu for “Login Window” (or, at a command line, type “gksudo gdmsetup”). Go to the “local” tab.

However, the custom welcome message is not displayed for a lot of (possibly most or all of) the themes, if you want a themed login window. My guess is that this is because these themes do not display a welcome message at all, period. To work around this, you can manually edit the .xml file of the theme you wish to use. Let’s assume you want to use the “Human” theme for your login screen. Pick that in the gdm setup window. Set your custom welcome message. Now, go to /usr/share/gdm/themes. You will see that this contains folders named after the different themes. You want to change the “Human” theme, so go to that folder. Now, using sudo, edit the file Human.xml. You will see that it contains xml markup, which is similar to hmtl. Add a section that looks like the following (I don’t think it matters where you add it. I added mine after the “ubuntu logo” section and it works fine):

  <!-- Welcome message (added by MP) -->
  <item type="label">
    <pos y="2%" x="2%"/>
    <normal color="#000000" font="Sans 14"/>
    <!-- Stock label for: Welcome to %h -->
    <stock type="welcome-label"/>
  </item>

Of course, you can change the position, color and font; this should be easy to figure out. Save the file. Next time you log out, you will see the custom welcome message that you have defined in the GUI for the gdm settings on your login screen.

R: Logical operators: Beware of the difference between “&&” and “&”

September 12th, 2008

There’s a tricky bit about R‘s logical operators, and though it’s described in the help pages that you get when you type, for example,

?"&"

I still fall from it from time to time. (I think it has to do with my rudimentary knowledge and usage of “&&” for if-statements in bash shell scripts.

Below I just go through “&&” and “&”. Obviously, this also applies to “||” and “|”.

Here’s a little demo to remind me and to demonstrate this to newbies:

> 1==1
[1] TRUE
> 1==1 & 1==2
[1] FALSE
> 1==1 && 1==2
[1] FALSE

So far, so good. Now look what happens if we apply this to vectors:

> 1:3==1:3
[1] TRUE TRUE TRUE
> 1:3==c(1,3,3)
[1]  TRUE FALSE  TRUE
> 1:3==1:3 & 1:3==c(1,3,3)
[1]  TRUE FALSE  TRUE

This is what you probably want in most cases: element-wise comparison. The “&” here compares each element in the vector “TRUE TRUE TRUE” to the corresponding element in “TRUE FALSE TRUE” and returns a “TRUE” each time they match and a “FALSE” if they don’t. Now look what happens if we use “&&”:

> 1:3==1:3 && 1:3==1:3
[1] TRUE
> 1:3==1:3 && 1:3==c(1,3,3)
[1] TRUE

For “&&”, as the R help page says, “The longer form evaluates left to right examining only the first element of each vector.”

This is quite obvious in this example, but it can get confusing when you use a logical operator to index a vector. Watch this:

> x <- 1:5
> x[x<5]
[1] 1 2 3 4
> x[x<5 & x>2]
[1] 3 4

Fine.

> x[x<5 && x>2]
integer(0)

The reason:

> x>2 & x<5
[1] FALSE FALSE  TRUE  TRUE FALSE
> x>2 && x<5
[1] FALSE

So in the first case, R "sees"

> x[c(FALSE,FALSE,TRUE,TRUE,FALSE)]

and in the second case, it sees:

> x[FALSE]

As long as the first element compares with "FALSE", you're actually lucky, because the error will be obvious. It's tricky when "&&" evaluates to "TRUE" when it looks at the first element, because some R functions will recycle input if it is too short, and this can lead to things like:

> x <- 1:10
> y <- c(1,3:11)
> x==y
 [1]  TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
> x[x==1 & y==1]
[1] 1
> x[x==1 && y==1]
 [1]  1  2  3  4  5  6  7  8  9 10

So basically, for logical comparison, stick to "&" unless you know you need "&&".

By the way, if you want to see the values that are elements of both x an y, use "%in%":

> x[x%in%y]
[1]  1  3  4  5  6  7  8  9 10
> y[y%in%x]
[1]  1  3  4  5  6  7  8  9 10

But don't do:

> y[x%in%y]
[1]  1  4  5  6  7  8  9 10 11

This indexes y using the logical vector returned by "x%in%y", which is of course:

> x%in%y
 [1]  TRUE FALSE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE