Programatically determine if an script is being executed on laptop or desktop?

18

3

Is there any reliable way to determine (programmatically) from within a bash script if it is being executed on a laptop or a desktop computer?

I could obviously just prompt the user to ask them, but that is pretty clunky.

PseudoPsyche

Posted 2015-02-13T20:21:20.420

Reputation: 402

1I'd say why you need to know? Are you worried about battery life – Rich Homolka – 2015-02-17T22:29:13.243

3The script is doing some system setup for the user, and part of that is configuring some power saving settings if the device is a laptop. – PseudoPsyche – 2015-02-17T23:18:29.583

Answers

29

Looking at whether or not the system has a battery is not reliable - a UPS connected to the system (not just for power, but over USB as well for automatic shutdown and battery monitoring) may show up as a battery.

There is a nice reliable way however:

dmidecode --string chassis-type

On a laptop, this will return one of "Laptop", "Notebook" "Portable", or "Sub Notebook" (depending on what the manufacturer coded into the BIOS). There is a full list of possible values at "Identifying the Chassis Type of a Computer" in the Windows 2000 Scripting Guide - don't worry about it being a Microsoft TechNet page, this is not OS specific.

dmidecode can also get information about the hardware manufacturer, system serial number (sometimes), etc.

Grant

Posted 2015-02-13T20:21:20.420

Reputation: 1 744

I have a UPS controlled via USB for automatic shutdown and battery monitoring with Network UPS Tool. It is does not show up as a "battery" on the Desktop. What configuration are you using that under which a UPS appears in /sys/module/battery?

– John1024 – 2015-02-14T07:35:03.687

This works better than the /sys/module/battery method: My two Ubuntu 14.04 desktops answer "Desktop" and "Low Profile Desktop", respectively, and the one with CentOS 6.5 says "Unknown". The one with CentOS 5.3 doesn't recognize the keyword "chassis-type". The Laptop I tried it on says "Notebook". But it's a drawback that you need root access. – Thomas Padron-McCarthy – 2015-02-14T09:36:54.367

I really like this answer! – Lembik – 2015-02-14T14:31:42.197

+1 for distribution independence. I tested it successfully on several machines. The only machine on which dmidecode gave a less than helpful answer was an Aspire netbook returned a chassis type of Other. – John1024 – 2015-02-15T22:07:31.750

this answer requires sudo, so is not viable for things like .bashrc files. Querying the contents of /sys/class/dmi/id/chassis_type, which is just a single number, is much better (as another answer below pointed out). – xdavidliu – 2019-10-05T20:05:23.880

9

To avoid using sudo, you can read the contents of /sys/class/dmi/id/chassis_type. It appears conform to the following table:

  • 1 Other
  • 2 Unknown
  • 3 Desktop
  • 4 Low Profile Desktop
  • 5 Pizza Box
  • 6 Mini Tower
  • 7 Tower
  • 8 Portable
  • 9 Laptop
  • 10 Notebook
  • 11 Hand Held
  • 12 Docking Station
  • 13 All in One
  • 14 Sub Notebook
  • 15 Space-Saving
  • 16 Lunch Box
  • 17 Main System Chassis
  • 18 Expansion Chassis
  • 19 SubChassis
  • 20 Bus Expansion Chassis
  • 21 Peripheral Chassis
  • 22 Storage Chassis
  • 23 Rack Mount Chassis
  • 24 Sealed-Case PC

demure

Posted 2015-02-13T20:21:20.420

Reputation: 4 605

Source for the table? And is 'lunch box' a joke?! – OJFord – 2019-07-14T20:03:49.210

1

@OJFord I do not have a citation at this time. As far as 'lunchbox', it is a nickname give to a form factor. I've worked with a few lunchboxes and pizzaboxes before. While this link may not last years, you can see some very modern lunchbox computers http://www.theportablepc.com/portable-pc.html

– demure – 2019-07-14T22:46:12.017

1

Grant's answer contains a citation from microsoft: https://docs.microsoft.com/en-us/previous-versions/tn-archive/ee156537(v=technet.10)

– demure – 2019-07-14T22:58:29.273

Thanks! Now I want one... But I suspect my wallet doesn't. – OJFord – 2019-07-15T06:04:51.440

This was the only solution that worked for me without needing to sudo. The battery-based solutions either said my ubuntu desktop was a laptop, or said my debian laptop was a desktop. – xdavidliu – 2019-10-05T19:54:38.860

Pizza box? How would it even detect that it's running in a pizza box? – Cestarian – 2020-02-01T04:18:57.023

9

Debian Solution:

To find whether a machine running Debian is a laptop, try:

[ -d /sys/module/battery ] && echo "Yes it's a laptop"

This approach does not require root privileges.

On other distributions, however, this directory seems to exist, at least in skeleton form, regardless of whether or not there is a battery. From the comments (below), these distributions include CentOS, Ubuntu, and the Ubuntu-derived distribution of Linux Mint.

More General Solution

Although it does not work on my Debian systems, the solution proposed by Alex reportedly works on Ubuntu & CentOS. Thus suggests, for greater generality, a possible combined solution:

[ -f /sys/module/battery/initstate ] || [ -d /proc/acpi/battery/BAT0 ] && echo "Yes it's a laptop"

This approach does not require root privileges.

More Details

On a Debian system with an actual battery, the /sys/module/battery directory contains many files. One such file is /sys/module/battery/initstate which contains the text live. On Ubuntu, however, these files do not exist even on actual laptops. Thus, it appears that the presence of the file /sys/module/battery/initstate can be used to test for a laptop running Debian.

On Debian systems that I tested, by contrast, the /proc/acpi/battery directory did not exist.

John1024

Posted 2015-02-13T20:21:20.420

Reputation: 13 893

1Isn't it possible that the second command could still return true in the case of a desktop with a UPS? – PseudoPsyche – 2015-02-13T20:36:59.333

3@PseudoPsyche I just tested it on a desktop with a UPS and it returned false (not a laptop). – John1024 – 2015-02-13T20:41:32.560

Doesn't a UPS go between the wall socket and a computer power socket? – Jon – 2015-02-13T23:23:49.407

1What is that first command doing there? – AndreKR – 2015-02-14T02:11:14.827

@AndreKR It was there because the wording of the question was originally ambiguous. – John1024 – 2015-02-14T02:15:18.233

1Apparently my 4U IBM server with an APC SmartUPS plugged in over USB is a laptop. I certainly wouldn't want that thing on my lap all day! (ie, if it has a UPS plugged in and configured for shutdown/monitoring, that directory will exist) – Grant – 2015-02-14T03:31:01.560

What happens when a laptop doesn't have a battery installed? – nobody – 2015-02-14T04:08:04.470

1@Chipperyman “Doesn't a UPS go between the wall socket and a computer power socket?” Yes, and many UPS setups—including consumer level—allow you to hookup a USB cable to get battery info and alerts on your desktop. – JakeGould – 2015-02-14T04:16:15.557

1This failed on my home desktop, which is a standard Mint install. Alex's answer below worked fine, on the other hand. It seems like a robust solution ought to check whether the battery hardware is actually physically present instead of merely checking for the existence of a battery management module, which may just happen to have been installed by default. – Thomas – 2015-02-14T08:53:07.120

This does not seem to be very reliable. I just tried this on four different desktop computers: two with Ubuntu 14.04, one with CentOS 5.2, and one with CentOS 6.5. None of them has a battery or a UPS. Still, all four of them had /sys/module/battery. – Thomas Padron-McCarthy – 2015-02-14T09:26:40.853

This doesn't work sadly. I tried it on my desktop just now and got "Yes it's a laptop". dmidecode --string chassis-type on the other hand did report "Desktop" – Lembik – 2015-02-14T14:32:40.573

@ThomasPadron-McCarthy I tested with Ubuntu-14.04 (live) and revised the answer. If you have the time and interest, it would be appreciated if you would check the revised answer on your systems. – John1024 – 2015-02-14T21:34:08.197

+1 because it doesnt require root privileges. If you have root, dmidecode is probably the more reliable answer, but without it the revisted version her is useful. – Grant – 2015-02-15T04:07:31.383

@John1024: It still doesn't work for me. The directory is not fully populated on the four desktops, so the file /sys/module/battery/initstate doesn't exist, but unfortunately the directory isn't populated on the laptop either (a Lenovo ThinkPad E330 with Ubuntu 14.04). So it still doesn't work for me. The /proc method works on all five machines, though. – Thomas Padron-McCarthy – 2015-02-15T10:28:35.573

@ThomasPadron-McCarthy Thanks much for the results: I've completely rewritten the answer. The /proc method does not work on either of the Debian laptops that I tested. – John1024 – 2015-02-15T21:59:13.750

8

I'd check if the computer has a battery installed. And the following is one way to test:

if [ -d /proc/acpi/battery/BAT* ]; then
  echo has a battery
fi

Alex

Posted 2015-02-13T20:21:20.420

Reputation: 824

This method gave the correct answer on all five computers I tried it on: two desktops with Ubuntu 14.04, one desktop with CentOS 5.3, one desktop with CentOS 6.5, and one laptop with Ubuntu 14.04. Also, it doesn't require root access. Of the three methods in the answers, my tests indicate that this may, tentatively, be the best one. – Thomas Padron-McCarthy – 2015-02-14T09:39:42.447

This works for me. – Lembik – 2015-02-14T14:38:02.117

This did not work on the two Debian laptops that I tested but +1 for working on a variety of other important distributions. – John1024 – 2015-02-15T22:01:41.327

Doesn't work for me (Toshiba Notebook), because my battery is named BAT1. I don't know how many other possible names there might be. – Joe – 2015-02-17T06:42:23.150

@Joe Change BAT0 to BAT* -- it should detect all variations. – Alex – 2015-02-17T17:24:15.907

@Alex - Yes. I just wanted to point out that the hard coded BAT0 wasn't reliable. You might want to edit this into your answer. – Joe – 2015-02-17T21:28:30.550

This doesn't work on Manjaro – Richard de Wit – 2018-10-07T18:03:00.057

this did not work on my debian laptops. – xdavidliu – 2019-10-05T19:49:55.373

1

If checking for battery existence is good enough, you can use this shell function:

# Checks whether system is a laptop.
#
# @returns {bool}   true if system is a laptop.
function is_laptop() {
    local d
    for d in /sys/class/power_supply /proc/acpi/battery; do
        [[ -d "$d" ]] && find $d -mindepth 1 -maxdepth 1 -name 'BAT*' -print0 -quit 2>/dev/null | grep -q . && return 0
    done

    # note we're checking /sys/class/power_supply/battery/status for WSL
    for d in /sys/class/power_supply/battery/status /sys/module/battery/initstate; do
        [[ -f "$d" ]] && return 0
    done

    return 1
}

Have been using this on Debian for years. Note this works also for Debian running in WSL or virtualbox.

Edit: generalized from other answers in this thread to catch more cases.

laur

Posted 2015-02-13T20:21:20.420

Reputation: 193