7

For example, to distinguish between Linux and Windows, I can use (when (eq system-type 'gnu/linux).

Is there a way to distinguish between Linux distributions, such as Ubuntu vs CentOS?

nanny
  • 5,704
  • 18
  • 38
yuxuan
  • 781
  • 4
  • 15

4 Answers4

6

Here's a quick custom function definition for your init file:

(defun which-linux-distribution ()
  "from lsb_release"
  (interactive)
  (when (eq system-type 'gnu/linux)
     (shell-command-to-string "lsb_release -sd")))

then run it as:

M-x which-linux-distribution

or test for a known distribution, for example, as:

(when (eq which-linux-distribution 'LinuxMint) 
     ....)

for unknown distributions or systems without the lsb_release tool, which-linux-distribution returns null, thereby stopping at the when test.

Emacs User
  • 5,553
  • 18
  • 48
4

There's no real standard method to detect the Linux distribution that a program is running under. Well, actually, there's a de jure standard: the lsb_release program. lsb_release -sir displays the name of the distribution and its version number. However, many Linux systems don't have the lsb_release program installed. Several distributions don't include it in the default installation.

However, you probably don't want to do this. How will you cope with unknown distributions? Say you have code for Debian and Fedora, and someone creates a new distribution derived from Debian, with its own name: your code wouldn't know that it should use the Debian-specific code.

Instead of testing the distribution, test for the behavior that matters. If different distributions put files in different directories, look for the directory that contains the file you want. If different distributions include different packages, check which packages are available. If a distribution has fixed a bug, test whether the bug is present and apply your workaround only if it is, and so on.

  • What's wrong with checking for a known string in a known distribution? It may suffice here in this case if further actions depended on that string. – Emacs User Nov 19 '15 at 01:49
  • @EmacsUser Because that would miss a derived distribution that differs in name and in ways you don't care about, but not in the ways you care about. And conversely that would misclassify a system where the administrator or the user has modified a configuration that you do care about. – Gilles 'SO- stop being evil' Nov 19 '15 at 10:30
  • Then don't run the specialized code that depends on knowing for sure the specific distribution. It's how we currently deal wth change in strings representing what OS is running on a system or how websites used to handle browser strings. But if machines are under the control of the admin, there is no question about "unknown distributions". – Emacs User Nov 19 '15 at 10:53
3

The variable operating-system-release might be helpful. On my Arch Linux VPS, it is set to 3.14.1-1-ARCH. On Windows, it's nil.

So to check if I'm on Arch, I would do something like this:

(when (string-match-p "ARCH" operating-system-release)
  ...)

This variable contains the same value output by the Linux command uname -r.

nanny
  • 5,704
  • 18
  • 38
  • 1
    On my system, compiled from source on Debian, `operating-system-release` is 4.2.0-1-amd64, suggesting this isn't that useful when Emacs is built from source. – Tyler Nov 18 '15 at 20:49
  • @Tyler My Emacs is built from source as well, I guess it just varies by distro. – nanny Nov 18 '15 at 20:56
  • Actually this variable is just the same as running `uname -r`. – nanny Nov 18 '15 at 21:02
  • 2
    You may be interested by something like `(setq dist (shell-command-to-string "lsb_release -a | sed -n '$p' | awk '{print $2}'")) (message dist)`, returning "jessie" on Debian. I let you find the shell command that will work nice on all the distributions. – Nsukami _ Nov 18 '15 at 21:26
  • 1
    @Nsukami_ Probably `lsb_release -sc` avoids calling `sed` and `awk`. And `lsb_relase -sd` actually refers to the Distribution, not the particular version. – giordano Nov 18 '15 at 22:13
  • @giordano you're definitely right, just quickly typed what was in my mind. – Nsukami _ Nov 19 '15 at 00:37
0

using command cat /etc/*releasemaybe find out distribution.It is not always useful.I can get the below output with it.

Arch Linux release
LSB_VERSION=1.4
DISTRIB_ID=Arch
DISTRIB_RELEASE=rolling
DISTRIB_DESCRIPTION="Arch Linux"
NAME="Arch Linux"
PRETTY_NAME="Arch Linux"
ID=arch
ID_LIKE=archlinux
ANSI_COLOR="0;36"
HOME_URL="https://www.archlinux.org/"
SUPPORT_URL="https://bbs.archlinux.org/"
BUG_REPORT_URL="https://bugs.archlinux.org/"

I can get distribution and the based distribution by ID and ID_LIKE,so I use the following elisp do it.

(defun guess-linux-release(regexp)
  "Guess linux release"
  (let ((maybe-get-dis-str (shell-command-to-string "cat /etc/*release")))
    (with-temp-buffer
      (insert maybe-get-dis-str)
      (beginning-of-buffer)
      (condition-case nil
          (progn
            (search-forward-regexp regexp)
            (downcase (buffer-substring (match-beginning 1) (match-end 1))))
        (search-failed nil)))))

(defun guess-linux-based-distribution()
  "Guess linux distribution family"
  (guess-linux-release "^ID_LIKE=\"?\\([a-zA-Z ]*\\)\"?$"))

(defun guess-linux-distribution()
  "Guess linux distribution"
  (guess-linux-release "^^^^^ID=\"?\\(\\w*\\)\"?$"))
djangoliv
  • 3,169
  • 16
  • 31