How-To: Set up multi-head X in Debian using Nvidia cards

I just had to set up a multi-head system in Debian and it consumed way too much of my time. I did see a lot of articles about it online but they all had a few common threads.

First, they all mentioned Xinerama was deprecated which initially scared me off of it. Xinerama is deprecated but there’s no replacement so for now I’m using it until it’s replacement is mature. Wayland is a system that keeps getting mentioned but seems too far off to be considered for me.

Second, they didn’t clearly outline how they determined all of their display information. Some were better than others but I need to build a real list of commands to get things done properly and repeatably since I know I will have to do this again at some point.

So, let’s go over what you need to do and how I got to a working system with three side-by-side displays.

My system consists of two Nvidia GTX 470 cards. Each card has two DVI outputs but I only have three displays. Therefore one card has two displays connected to it (the left and right displays) and another card has one display connected to it (the center display).

What you’ll want to do is first figure out which display is connected to which card and how Linux enumerates them in your system. To do this you should be in text mode (not X!) and go to the “/sys/class/drm” directory. Let’s take a look at mine:


tim@desktop:/sys/class/drm$ ls -la
total 0
drwxr-xr-x  2 root root    0 Jan 15 19:21 .
drwxr-xr-x 40 root root    0 Jan 15 19:21 ..
lrwxrwxrwx  1 root root    0 Jan 15 19:21 card0 -> ../../devices/pci0000:00/0000:00:01.0/0000:01:00.0/drm/card0
lrwxrwxrwx  1 root root    0 Jan 15 19:21 card0-DVI-I-1 -> ../../devices/pci0000:00/0000:00:01.0/0000:01:00.0/drm/card0/card0-DVI-I-1
lrwxrwxrwx  1 root root    0 Jan 15 19:21 card0-DVI-I-2 -> ../../devices/pci0000:00/0000:00:01.0/0000:01:00.0/drm/card0/card0-DVI-I-2
lrwxrwxrwx  1 root root    0 Jan 15 19:21 card0-HDMI-A-1 -> ../../devices/pci0000:00/0000:00:01.0/0000:01:00.0/drm/card0/card0-HDMI-A-1
lrwxrwxrwx  1 root root    0 Jan 15 19:21 card1 -> ../../devices/pci0000:00/0000:00:03.0/0000:02:00.0/drm/card1
lrwxrwxrwx  1 root root    0 Jan 15 19:21 card1-DVI-I-3 -> ../../devices/pci0000:00/0000:00:03.0/0000:02:00.0/drm/card1/card1-DVI-I-3
lrwxrwxrwx  1 root root    0 Jan 15 19:21 card1-DVI-I-4 -> ../../devices/pci0000:00/0000:00:03.0/0000:02:00.0/drm/card1/card1-DVI-I-4
lrwxrwxrwx  1 root root    0 Jan 15 19:21 card1-HDMI-A-2 -> ../../devices/pci0000:00/0000:00:03.0/0000:02:00.0/drm/card1/card1-HDMI-A-2
lrwxrwxrwx  1 root root    0 Jan 15 19:21 controlD64 -> ../../devices/pci0000:00/0000:00:01.0/0000:01:00.0/drm/controlD64
lrwxrwxrwx  1 root root    0 Jan 15 19:21 controlD65 -> ../../devices/pci0000:00/0000:00:03.0/0000:02:00.0/drm/controlD65
lrwxrwxrwx  1 root root    0 Jan 15 19:21 ttm -> ../../devices/virtual/drm/ttm
-r--r--r--  1 root root 4096 Jan 15 19:21 version

Here you can see that I have two cards named card0 and card1. Card 0 has three connectors on it named card0-DVI-I-1, card0-DVI-2, and card0-HDMI-A-1. Card 1 has three connectors on it named card1-DVI-3, card1-DVI-4, card1-HDMI-A-2. We will need this information later to build our xorg.conf so keep it handy.

Now you’ll want to determine which monitor is hooked up to which card and port. If you are using this setup in Windows already you are not guaranteed that the cards are recognized in the same order so just forget what Windows has told you. To figure out which is which first make sure all of your displays are connected to your cards. Then ask Linux which displays are connected by executing this command:

ls /sys/class/drm/*/status | xargs -I {} -i bash -c "echo -n {}: ; cat {}"

This will show you which connectors think that they have something connected to them. My output looks like this:

tim@desktop:/sys/class/drm$ ls /sys/class/drm/*/status | xargs -I {} -i bash -c "echo -n {}: ; cat {}"
/sys/class/drm/card0-DVI-I-1/status:connected
/sys/class/drm/card0-DVI-I-2/status:connected
/sys/class/drm/card0-HDMI-A-1/status:disconnected
/sys/class/drm/card1-DVI-I-3/status:connected
/sys/class/drm/card1-DVI-I-4/status:disconnected
/sys/class/drm/card1-HDMI-A-2/status:disconnected

So now I know that card0 is the card that has my two displays attached to it and card1 is the card that has my two displays attached to it. That tells me that “DVI-I-3″ is my center display and “DVI-I-1″ and “DVI-I-2″ are my left and right displays. We’ll figure out which is left and which is right in a minute.

For now, let’s figure out which PCI device Linux considers these devices. You can do this by running this command:

ls -la /sys/class/drm/card?

My output looks like this:

tim@desktop:~$ ls -la /sys/class/drm/card?
lrwxrwxrwx 1 root root 0 Jan 15 19:21 /sys/class/drm/card0 -> ../../devices/pci0000:00/0000:00:01.0/0000:01:00.0/drm/card0
lrwxrwxrwx 1 root root 0 Jan 15 19:21 /sys/class/drm/card1 -> ../../devices/pci0000:00/0000:00:03.0/0000:02:00.0/drm/card1

Look at the numbers directly before “drm”. They are “0000:01:00.0″ for card 0 and “0000:02:00.0″ for card 1. This tells us that card 0 is PCI device 1 and card 1 is PCI device 2. Keep these numbers handy too.

The next step is to figure out which connectors is the left and which is the right. You can do this by guessing but let’s just get a definitive answer. Type the same command we used before to get the list of all of our displays (or press the up arrow if your shell supports that to get to the last command) but don’t run it yet. Now disconnect one display, press enter, and reconnect it. I suggest you do this so that just in case you disconnect the display that your terminal is running on you can still run the command and see the results when you reconnect it.

In my case I got this output when my right display was disconnected:

tim@desktop:/sys/class/drm$ ls /sys/class/drm/*/status | xargs -I {} -i bash -c "echo -n {}: ; cat {}"
/sys/class/drm/card0-DVI-I-1/status:disconnected
/sys/class/drm/card0-DVI-I-2/status:connected
/sys/class/drm/card0-HDMI-A-1/status:disconnected
/sys/class/drm/card1-DVI-I-3/status:connected
/sys/class/drm/card1-DVI-I-4/status:disconnected
/sys/class/drm/card1-HDMI-A-2/status:disconnected

Now I know that “DVI-I-1″ is my right display since before it was connected and when I ran the command it was disconnected. By elimination I know “DVI-I-2″ is my right display. If you have more displays you’ll need to do this a few more times.

Let’s recap. I know that card 0 has two displays on it, its DVI-I-1 connector is my right display, its DVI-I-2 connector is my left display. Card 1 has one display on it and its DVI-I-3 connector is my center display. With that information I can start building my xorg.conf file. I’ll show you what I ended up with and then break it out and explain it:

Section "ServerLayout"
	Identifier  "X.org Configured"
	Option      "Xinerama"            "on"
	Screen      0  "Screen0" 0 0
	Screen      1  "Screen1" RightOf  "Screen0"
	Screen      2  "Screen2" LeftOf   "Screen0"
	InputDevice    "Mouse0"           "CorePointer"
	InputDevice    "Keyboard0"        "CoreKeyboard"
EndSection

Section "Files"
	ModulePath   "/usr/lib/xorg/modules"
	FontPath     "/usr/share/fonts/X11/misc"
	FontPath     "/usr/share/fonts/X11/cyrillic"
	FontPath     "/usr/share/fonts/X11/100dpi/:unscaled"
	FontPath     "/usr/share/fonts/X11/75dpi/:unscaled"
	FontPath     "/usr/share/fonts/X11/Type1"
	FontPath     "/usr/share/fonts/X11/100dpi"
	FontPath     "/usr/share/fonts/X11/75dpi"
	FontPath     "/var/lib/defoma/x-ttcidfont-conf.d/dirs/TrueType"
	FontPath     "built-ins"
EndSection

Section "Module"
	Load  "glx"
	Load  "dbe"
	Load  "dri"
	Load  "record"
	Load  "dri2"
	Load  "extmod"
EndSection

Section "InputDevice"
	Identifier  "Keyboard0"
	Driver      "kbd"
EndSection

Section "InputDevice"
	Identifier  "Mouse0"
	Driver      "mouse"
	Option	    "Protocol" "auto"
	Option	    "Device" "/dev/input/mice"
	Option	    "ZAxisMapping" "4 5 6 7"
EndSection

Section "Device"
	Identifier  "Device1"
	Driver      "nouveau"
	BusID       "PCI:1:0:0"
	Option      "ZaphodHeads" "DVI-I-1"
	Screen      0
EndSection

Section "Device"
	Identifier  "Device2"
	Driver      "nouveau"
	BusID       "PCI:1:0:0"
	Option      "ZaphodHeads" "DVI-I-2"
	Screen      1
EndSection

Section "Device"
	Identifier  "Device0"
	Driver      "nouveau"
	BusID       "PCI:2:0:0"
	Option      "ZaphodHeads" "DVI-I-3"
	Screen      0
EndSection

Section "Screen"
	Identifier	"Screen0"
	Device		"Device0"
EndSection

Section "Screen"
	Identifier	"Screen1"
	Device		"Device1"
EndSection

Section "Screen"
	Identifier	"Screen2"
	Device		"Device2"
EndSection

Here’s the explanation of each section:

Section "ServerLayout"
	Identifier  "X.org Configured"
	Option      "Xinerama"            "on"
	Screen      0  "Screen0" 0 0
	Screen      1  "Screen1" RightOf  "Screen0"
	Screen      2  "Screen2" LeftOf   "Screen0"
	InputDevice    "Mouse0"           "CorePointer"
	InputDevice    "Keyboard0"        "CoreKeyboard"
EndSection

This is the server layout section that declares how the screens are laid out and what input devices we’re using. It specifies a name of “X.org Configured” since I used another configuration as a baseline for this. You can change that name to whatever you’d like. Then it specifies that Xinerama is on. This means that you can drag windows back and forth between screens. It has some downsides but they are outweighed by the convenience of placing windows anywhere across all of your displays.

Then it specifies three “screen” entries. Later on “Screen0″ will by my center screen. “0 0″ just means that that screen starts at pixel 0,0. “Screen1″ will be might right screen so it will be to the right of my center screen. In xorg.conf language that is done with “RightOf”. “Screen2″ will be my left screen so it is “LeftOf” my center screen.

Section "Files"
	ModulePath   "/usr/lib/xorg/modules"
	FontPath     "/usr/share/fonts/X11/misc"
	FontPath     "/usr/share/fonts/X11/cyrillic"
	FontPath     "/usr/share/fonts/X11/100dpi/:unscaled"
	FontPath     "/usr/share/fonts/X11/75dpi/:unscaled"
	FontPath     "/usr/share/fonts/X11/Type1"
	FontPath     "/usr/share/fonts/X11/100dpi"
	FontPath     "/usr/share/fonts/X11/75dpi"
	FontPath     "/var/lib/defoma/x-ttcidfont-conf.d/dirs/TrueType"
	FontPath     "built-ins"
EndSection

Section "Module"
	Load  "glx"
	Load  "dbe"
	Load  "dri"
	Load  "record"
	Load  "dri2"
	Load  "extmod"
EndSection

I left these two sections completely stock. They’re magic for now so don’t make any changes to them.

Section "InputDevice"
	Identifier  "Keyboard0"
	Driver      "kbd"
EndSection

Section "InputDevice"
	Identifier  "Mouse0"
	Driver      "mouse"
	Option	    "Protocol" "auto"
	Option	    "Device" "/dev/input/mice"
	Option	    "ZAxisMapping" "4 5 6 7"
EndSection

These two sections specify our input devices. These are stock also so you can leave them alone too.

Section "Device"
	Identifier  "Device1"
	Driver      "nouveau"
	BusID       "PCI:1:0:0"
	Option      "ZaphodHeads" "DVI-I-1"
	Screen      0
EndSection

Here’s some more configuration we have to do. Remember that DVI-I-1 is our right display and we are calling it “Screen1″. In this section we need to create a device for it that tells X which drive, card, and connector it uses as well as which screen it is relative to its specific graphics card. We’ll call it “Device1″, use the open-source Nvidia driver called “Nouveau”, tell it to use PCI device 1 (since card 0 was device 1) with the “PCI:1:0:0″ string, then tell it the connector is “DVI-I-1″ with the “ZaphodHeads” option, and finally that this is the first display (display 0) on this graphics card.

Section "Device"
	Identifier  "Device2"
	Driver      "nouveau"
	BusID       "PCI:1:0:0"
	Option      "ZaphodHeads" "DVI-I-2"
	Screen      1
EndSection

For our left display we have similar settings but the connector is “DVI-I-2″ and this is the second display (display 1) on this graphics card. We also call this “Device2″.

Section "Device"
	Identifier  "Device0"
	Driver      "nouveau"
	BusID       "PCI:2:0:0"
	Option      "ZaphodHeads" "DVI-I-3"
	Screen      0
EndSection

Our center screen is “Device0″ and it is on a different graphics card. Remember card 1 was PCI device 2 so we use “PCI:2:0:0″ here and specify the connector as “DVI-I-3″. This is the first display (display 0) on this graphics card.

Section "Screen"
	Identifier	"Screen0"
	Device		"Device0"
EndSection

Section "Screen"
	Identifier	"Screen1"
	Device		"Device1"
EndSection

Section "Screen"
	Identifier	"Screen2"
	Device		"Device2"
EndSection

Finally, these sections map our devices to name screens. In this case DeviceX is ScreenX. Nothing fancy goes on here.

Replace or create your xorg.conf using the steps you see here and you should be up and running in no time. I had to change from Gnome to Xfce since Gnome had a really tall black bar that took over my center display that I couldn’t get rid of. If you run into the same problem try Xfce or another window manager instead.

Good luck and post in the comments if you found this useful or need some assistance.

How-To: Install Google’s Android Eclipse plugin (and/or adb) on 64-bit Debian/Ubuntu

Today I had to reinstall the Android plugin on my system and I recently upgraded to a 64-bit development VM. To my surprise the installation didn’t go smoothly at all. After restarting Eclipse twice I was constantly presented with two error messages “Failed to parse the output of ‘adb version’” and “adb: error while loading shared libraries: libncurses.so.5: cannot open shared object file: No such file or directory”. Your system may also present another error message that reads “adb: error while loading shared libraries: libstdc++.so.6: cannot open shared object file: No such file or directory”.

I could see that it was looking for libncurses.so.5 however I know that ncurses is already installed on my machine in /lib as /lib/libncurses.so.5. So where exactly was Eclipse/adb looking for it? It turns out that it wants to find its libraries in the /lib32 directory but you can’t just symlink it or you’ll get an error that reads “wrong ELF class: ELFCLASS64″. adb needs to have the 32-bit versions installed or it won’t function at all.

So to get up and running just run the following command to fix the issue:

sudo apt-get install lib32ncurses5 lib32stdc++6

After that just restart Eclipse and the issue should be fully put to bed. Let me know how it works out for you or if you run into trouble.

If you still run into trouble like an error message that reads “aapt: error while loading shared libraries: libz.so.1: cannot open shared object file: No such file or directory” you need to install the ia32-libs like this:

sudo apt-get install ia32-libs

Then rebuild your project and the errors should be gone.

UPDATE 2012-02-14: Rortian reports that the following command words on Fedora 16:

yum install ncurses-libs.i686 libstdc++.i686 libgcc.i686

How-To: Run TeamViewer 6 as root in Linux (Debian, Ubuntu)

If you are reading this article I, unlike the rest of the Internet, will assume you have a good reason to run Teamviewer as root. I won’t spend my time trying to talk you out of it. :)

You can accomplish this in just a few quick steps:

1) Install Teamviewer 6
2) Try to run it as root, if you get the message “TeamViewer must not be executed as root!” go on to step 3. Otherwise, you are already set up.
3) Open /opt/teamviewer/teamviewer/6/bin/wrapper in your favorite text editor
4) Look for a line similar to this: “validate_user # die if root”
5) Put a single hash/octothorpe in front of the line and save it so it looks like “#validate_user # die if root”.
6) Restart Teamviewer as root and you’re good to go

Post in the comments if you used this tip and let me know if you run into any trouble. This should work on other versions of Linux but the files may be in different places. If you want to find your operating system’s copy of “wrapper” try running “locate wrapper | grep -i teamviewer” and it should come up in the list. If you don’t have locate installed you can try the much slower: “find / -name “wrapper” | grep -i teamviewer” to do the same thing. Good luck!

How-To: Convert from bzr to git on Debian/Ubuntu

For a brief period of time I was totally sold on Bazaar (AKA bzr) for my distributed version control needs.  Then I found out about github and the rest is history.  bzr is neat and has it’s advantages but github is just too hot a community to pass up.  Building skills on both would be great but realistically I’m only going to get good at the one that I use consistently.  So, git wins for me.

When I was using bzr I accumulated a bunch of code in bzr repositories that I now want to convert to git.  There are a bunch of tutorials out there on how to do this but they all didn’t work for some reason or another.  Here I have step by step instructions on how to move from bzr to git, with any branches you have created, that should work without fuss on both Debian and Ubuntu.

These instructions assume the following:

  1. You have a bzr repository that you’d like to become your master git branch that currently resides in a directory called bzr-master.
  2. You have one branch you’d like to bring into git as “branch-1″ that currently resides in a directory called bzr-branch-1.
  3. You want to call your new repository git-repo.

Obviously, you will have different master and branch names so fill those in appropriately.  They are bold faced and italicized where you will need to replace the names.

  • Step 1: Install bzr.
    sudo apt-get install bzr
  • Step 2: Install bzr-fastimport.
    sudo apt-get install bzr-fastimport
  • Step 3: Go to the parent directory that contains your two bzr branches in your shell.
  • Step 4: Create the new git repository and stay in that directory
    mkdir git-repo ; cd git-repo ; git init .
  • Step 5: Pull the master branch into git
    bzr fast-export --export-marks=../marks.bzr ../bzr-master | git fast-import --export-marks=../marks.git
  • Step 6: Pull branch-1 into git
    bzr fast-export --marks=../marks.bzr --git-branch=branch-1 ../bzr-branch-1 | git fast-import --import-marks=../marks.git --export-marks=../marks.git

Now if you do a git branch you should see the master branch as well as branch-1. Check the logs to make sure they’re complete, nuke the marks.bzr and marks.git files, and then push them to github! :)

How-To: Install NodeJS, CouchDB, and npm on Debian (the easy way)

Are you looking for a no-nonsense way to install all of these applications and don’t want to dig through any documentation?  Just run this list of commands (replacing the word CORES for the number of cores you have):

git clone https://github.com/joyent/node.git
cd node
export JOBS=CORES # optional, sets number of parallel commands.
mkdir ~/local
./configure --prefix=$HOME/local/node
make -jCORES
make install
cd ..
git clone git://github.com/apache/couchdb.git
cd couchdb
sudo apt-get install automake
sudo apt-get install libmozjs-dev
sudo apt-get install libicu-dev
sudo apt-get install erlang
./bootstrap
./configure --prefix=$HOME/local/couchdb
make -jCORES
make install

After that, update your path in .bashrc by adding this line to the bottom:

export PATH=$HOME/local/node/bin:$HOME/local/couchdb/bin:$PATH

Now, you can run both NodeJS and CouchDB from anywhere once you log out and log back in again.  Finally, installing npm is just one more step:

curl http://npmjs.org/install.sh | sh

That’s it, you’ve now got all of the latest code installed. To start couchdb run

couchdb -b

from anywhere and connect to Futon locally via http://localhost:5984/_utils/. BTW, to use CouchDB from NodeJS I recommend Cradle.

Mobile Analytics by Mixpanel