67

Ubuntu 20.04 has decided we need 4 clicks to shut down:

  1. Click top right of screen arrow-down
  2. Expand "power off/logout" panel
  3. Click "Power off"
  4. Confirm you want to power off by choosing power off vs reboot etc

Let's cut out at least 2 clicks here... how?

UPDATE: This is a "Lounge PC" - operated by mouse (no power button within reach as the laptop is closed). We watch a film, we want to click to shutdown and not type commands.

18
  • 7
    You can add a shutdown icon to the dock: askubuntu.com/q/1160508/480481
    – pomsky
    Jun 6, 2020 at 9:31
  • 2
    It will not reduce the number of clicks, but you need not move (or even use) the mouse or touchpad: ctrl + alt + t to open a terminal window, type poweroff and press the Enter key. I find this more convenient than those 4 clicks to shutdown.
    – sudodus
    Jun 6, 2020 at 9:32
  • 25
    How often are you shutting down that this is such an issue? Jun 6, 2020 at 23:09
  • 5
    Can be reduced to 0 clicks if you hold down the power button for 8 seconds.
    – user9123
    Jun 7, 2020 at 16:04
  • 16
    @developerbmw I shut down my PC multiple times a day. I don't want a system consume energy while I am not using it, i.e. lunch-break. Also the psychological factor "the machine is off. I am not working right now" is important to me. Marc might have similar opinions.
    – Hermann
    Jun 8, 2020 at 0:21

9 Answers 9

39

You can easily make it 2 clicks:

  1. Open Settings
  2. Go to "Power"
  3. Change the "Power button action" dropdown to "Power off"

Now click the physical power button on your device and then select power off from the prompt - that is 2 clicks (1 if you don't count pressing the power button as a click).

3
26

Reduce by two clicks

Option 1) Install the Poweroff Button on Topbar extension by Darknico. It adds a separate Power button on the right of the top bar.

Option 2) Create a "regular" launcher for "Power Off" (with thanks to pomsky). Either:

You may reduce with one more click by substituting the command in the launcher with "poweroff". Then, a single click on the launcher will immediately shut down the machine without confirmation dialog.

Reduce by one click

Option 3) Use the extension Bring Out Submenu Of Power Off/Logout Button by Pratap, or Simpler Off Menu by K3rcus. These extensions bring the items in the "Power Off/Log Out" submenu directly into the system menu, allowing to access them with one less click.

3
  • 2
    Just a pointer, in this answer, I used the gnome-session-quit --power-off command so that the user gets the confirmation dialog after clicking the shutdown icon. The process can be reduced by one step more by changing the Exec line to something like Exec=shutdown now. Then the system would shut down immediately after clicking the shutdown icon without showing any confirmation dialog.
    – pomsky
    Jun 6, 2020 at 11:31
  • 5
    I considered adding this (also the command poweroff will do), but it becomes the heck dangerous with the launcher approach. A single wrong click immediately would take the system down.
    – vanadium
    Jun 6, 2020 at 11:40
  • Of course, that's why I used the gnome-session-quit command instead in that answer. I just mentioned this point purely with respect to the "reducing number of steps as far as possible" aspect.
    – pomsky
    Jun 6, 2020 at 20:28
16

Getting it down to 1 "click" (technically a button press):

By default, ubuntu shuts down the machine when you press the power button.

Then just wait 60 seconds for the machine to power off instead of clicking again.

1
  • 3
    I've updated my question: this is a lounge PC/Laptop with closed lid and no easy way to access the power button. I want to reduce clicks not introduce buttons/typing.
    – Marc
    Jun 8, 2020 at 7:02
7

Keyboard shortkey screenshot

I have the habit of creating my own keyboard shortcut to shutdown the PC because this is lot easier and less painful.

I have used too many buttons to avoid any accidental shutdown.

You can decrease it and make it like Super+P or something like that if you are careful enough.

1
  • I use this, but for sleep mode, it works great. I feel it's faster than even 1 mouse click once you get used to it.
    – Mark
    Jun 9, 2020 at 13:45
6

The answer is 0.

Install KShutdown, specify how long are you going to be online. As long as you stick to the plan and not mess with the time and save whatever you're doing 2 minutes prior. The machine will turn itself off, without you even touching it.

If you want to write your own command, start the terminal and type:

sudo shutdown -h +30

+30 (minutes) is an example. Change it to however long you want to stay online. And if you want the machine to turn itself off at a specific time, try:

sudo shutdown -h 20:30

(time is hypothetical, change it to whatever you want).

Note: Without the -h or -r switch it isn't a valid command.

1
  • 2
    eehh ? it is methods from the old times, meh. Not usable at all.. How about tool, which will detect that computer is in the IDLE for X minutes/hours and then will pursuit shutdown automatically ?
    – Reishin
    Jun 7, 2020 at 23:41
3

0 clicks, a few clacks.

An alternative solution that doesn't require a mouse (just keyboard):

  1. Press and hold Ctrl+ALT+t

This brings up a terminal window.

  1. Type "poweroff" then hit the Enter key.
2
  • 1
    Fun fact: halt and init 0 both have fewer "clacks" than poweroff. Jun 11, 2020 at 6:07
  • OP doesn't have a keyboard, or at least easy access to one. Jun 11, 2020 at 19:43
2

Sony TV remote suspends laptop

This answer is based on IoT (Inernet of Things).

tvpowered (TV controls power to the computer) is a bash script. When you press the power button on your Sony TV remote:

  • The Sony TV will be shut off
  • The Google Android TV will be shut off
  • The light behind the Sony TV will be shut off
  • The light behind the Google TV will be shut off
  • The laptop will be put to sleep

Additionally the tvpowered script will:

  • Turn off picture of TV to save power when you are not watching movies on TV.
  • Display pop-up bubble when you change volume of TV used for listening to music.

volume change.gif

Please note this only works with Sony Bravia TVs.


Overview

When TV is turned off tvpowered automatically suspends, hibernates or powers off the laptop. Change the setting of SCTL global variable to control which action is taken.

tvpowered should be run as a normal user and called in Startup Applications.

Program design is straight forward:

  1. Wait for TV to be powered on.
  2. Begin fully active operation.
  3. Check if TV is powered off. If off go to step 5.
  4. Sleep for 3 seconds and repeat step 3.
  5. Suspend or Poweroff system when TV is powered off.
  6. If resuming from suspend go back to step 1.

In between these steps pop-up bubble messages appear on Desktop and are also logged to journalctl:

$ journalctl -xe | grep tvpower

Jun 11 18:11:20 tvpowered[27398]: TV is powered on. 'tvpowered' is now waiting for TV to power off.
Jun 11 18:11:47 tvpowered[28229]: TV Powered off. 'systemctl suspend' being called.
Jun 11 18:11:47 tvpowered[28238]: System powered back up. Checking if TV powered on. './tvpowered'.
Jun 11 18:12:26 tvpowered[31672]: TV is powered on. 'tvpowered' is now waiting for TV to power off.

tvpowered script

Copy and paste the script into a file on your computer and mark it executable with:

chmod a+x /path/to/tvpowered

Where /path/to/ is the directory name you created the file in.

You can also user your file manager (like Nautilus) to make the file executable.

In the script below there are a few constants you will need to set:

SCTL=suspend        # systemctl paramater: suspend or poweroff
IP=192.168.0.19     # IP address for Sony TV on LAN
ADB_IP=192.168.0.21 # IP address for Google TV on LAN for Android Debug Bridge
PWRD=123            # Password for Sony TV IP Connect

tvpowered complete bash script

#!/bin/bash

# NAME: tvpowered
# PATH: /usr/bin/ OR ~/bin (/home/USERNAME/bin) OR /mnt/e/bin/
#
# DESC: When TV is powered off automatically suspend the laptop.
# DATE: June 9, 2020.  Modified March 30, 2023.
#
# NOTE: Written for Ask Ubuntu question:
#       https://askubuntu.com/questions/1247484/
#       4-clicks-to-shut-down-ubuntu-can-we-reduce-this

# UPDT: Jun 10 2020: Make name politically correct for Microsoft guidelines.
#       Change name from 'slave2tv' to 'tvpowered'. Abandon approach of polling
#       i2c, drm, i915, nvidia, xrandr, etc to see if monitor turned off. Setup
#       WiFi on TV instead and use Sony REST API to communicate TV status.

#       Jun 11 2020: Add pop-up bubble status messages. Add dependencies.
#       Add TenMinuteSpam. Add WaitUserSignOn. Add $SCTL constant. Convert
#       in-line code to mainline format.

#       Oct 03 2020: If ethernet disconnected we don't want to suspend.
#       Add TenMinuteSpam. Add WaitUserSignOn. Add $SCTL constant. Convert
#       in-line code to mainline format.

#       Oct 18 2020: If WiFi disconnected we don't want to suspend.

#       Dec 23 2020: After resume turn off picture with power savings.

#       Dec 31 2020: Fast popping bubble messages when volume changes.

#       Jan 09 2021: Improve performance and reduce system resources.

#       Jan 31 2021: Switch from /tmp to /run/user/1000 (RAM).

#       Mar 13 2023: New IP address 19 after power outage.

#       Mar 26 2023: Change volume partial UTF-8 ticks from 4 to 8.

#       Mar 28 2023: Change call to `pictureoff`

#       Mar 30 2023: Google TV to sleep (TV Remote Power Off).

# Sources:

# https://gist.github.com/kalleth/e10e8f3b8b7cb1bac21463b0073a65fb#cec-sonycec
# https://pro-bravia.sony.net/develop/integrate/rest-api/spec/service/audio/v1_0/setAudioVolume/index.html
# https://developer.sony.com/develop/audio-control-api/get-started/http-example#tutorial-step-2
# https://en.wikipedia.org/wiki/CURL
# https://stackoverflow.com/questions/7172784/how-do-i-post-json-data-with-curl
# https://stackoverflow.com/questions/2829613/how-do-you-tell-if-a-string-contains-another-string-in-posix-sh

SCTL=suspend        # systemctl parameter: 'suspend' or 'poweroff'
IP=192.168.0.19     # IP address for Sony TV on LAN
ADB_IP=192.168.0.21 # IP address for Google TV on LAN for Android Debug Bridge
PWRD=123            # Password for Sony TV IP Connect (Pre-Shared key)

# Must have curl package.
command -v curl >/dev/null 2>&1 || { echo >&2 \
        "'curl' package required but it is not installed.  Aborting."; \
        exit 2; }

# Must have notify-send from libnotify-bin package
command -v notify-send >/dev/null 2>&1 || { echo >&2 \
        "'libnotify-bin' package required but it is not installed.  Aborting."; \
        exit 3; }

# Must have adb (Android Debug Bridge) package
command -v adb >/dev/null 2>&1 || { echo >&2 \
        "'adb' package required but it is not installed.  Aborting."; \
        exit 4; }

cURLit () {

    # $1 = JSON String in pretty format converted to file for cURL --data.
    # $2 = Sony subsystem to talk to, eg accessControl, audio, system, etc.
    # 3  = variable name to receive reply from TV

    local TEMP Result ReturnState

    # Declare mathres as reference to argument 3 provided (Bash 4.3 or greater)
    declare -n Result=$3  # ERROR: declare: `': not a valid identifier

    # Create temporary file in RAM for curl command
    TEMP=$(mktemp --tmpdir=/run/user/1000 tvpowered.XXXXXXXX)
    echo "$1" > "$TEMP"

    # -s = silent
    Result=$(curl -s -H "Content-Type: application/json; charset=UTF-8" \
             -H "X-Auth-PSK: $PWRD" \
             --data @"$TEMP" \
             http://$IP/sony/"$2")
    # echo "Result: $Result"    # Remove leading # for debugging
    ReturnState="$?"
    # TO-DO: check $? and if non-zero pop up dialog with $TEMP contents
    rm "$TEMP"

    # Test string
#curl -s -H "Content-Type: application/json; charset=UTF-8" -H "X-Auth-PSK: 123" --data "{ "method": "getPowerStatus", "id": 50, "params": [], "version": "1.0" }" http://192.168.0.16sony/system
} # cURLit

GetPowerStatus () {

    local Reply ReturnState

    # Copy and paste JSON strings from Sony website: 
    # https://pro-bravia.sony.net/develop/integrate/rest-api/spec/service/system/v1_0/getPowerStatus/index.html
    JSONstr='{
                "method": "getPowerStatus",
                "id": 50,
                "params": [],
                "version": "1.0"
             }'

    cURLit "$JSONstr" "system" Reply    # No $ for Reply variable! pass pointer
    ReturnState="$?"                    # Usually '6', not checked.

    #echo "ReturnState: $ReturnState Reply: $Reply"    # Remove # for debugging
    # Reply: {"result":[{"status":"active"}],"id":50}
    #    or: {"result":[{"status":"standby"}],"id":50}

    # Does 'active' substring exist in TV's reply?
    [[ "${Reply#*active}" != "$Reply" ]] && return 0

    # TV is turned off (standby) or no network (blank)
    return 1
    
} # GetPowerStatus

GetVolume () {

    # Copy and paste JSON strings from Sony website: 
    # https://pro-bravia.sony.net/develop/integrate/rest-api/spec/service/audio/v1_0/getVolumeInformation/index.html
    JSONstr='{
                "method": "getVolumeInformation",
                "id": 33,
                "params": [],
                "version": "1.0"
             }'
    
    # Then pass string to cURL for execution
    cURLit "$JSONstr" "audio" Reply

    # Sample output:
    #   Volume:, {"result":[[{"target":"speaker","volume":44,"mute":false,
    #   "maxVolume":100,"minVolume":0},{"target":"headphone","volume":15,
    #   "mute":false,"maxVolume":100,"minVolume":0}]],"id":33}

    Start="${Reply:41:4}"
    Volume=${Start%,*}

    return $Volume

} # GetVolume


Bar=""                          # Global Volume Level bar

VolumeBar () {

    Bar=""                      # Progress Bar / Volume level
    Len=25                      # Length of Progress Bar / Volume level
    Div=4                       # Divisor into Volume for # of full blocks
    Fill="▒"                    # Fill background up to $Len
    Parts=8                     # Divisor into  Volume for # of part blocks
    # UTF-8 left blocks: 1, 1/8, 1/4, 3/8, 1/2, 5/8, 3/4, 7/8
    Arr=("█" "▏" "▎" "▍" "▌" "▋" "▊" "█")

    FullBlock=$((${1} / Div))   # Number of full blocks
    PartBlock=$((${1} % Parts)) # Size of partial block (array index)

    while [[ $FullBlock -gt 0 ]]; do
        Bar="$Bar${Arr[0]}"     # Add 1 full block into Progress Bar
        (( FullBlock-- ))       # Decrement full blocks counter
    done

    # If remainder zero no partial block, else append character from array
    if [[ $PartBlock -gt 0 ]]; then
        Bar="$Bar${Arr[$PartBlock]}"
    fi

    while [[ "${#Bar}" -lt "$Len" ]]; do
        Bar="$Bar$Fill"         # Pad Progress Bar with fill character
    done

} # VolumeBar


log () {
    logger --id=$$ -t "tvpowered" "$1"
} # log


WaitForSignOn () {

    # tvpowered might be loaded during boot. The user name is required
    # for sending popup bubble messages and dialogs to screen. We must
    # wait until user signs on to get .Xauthority file settings.

    # code lifted from eyesome.sh
    SpamOn=10       # Causes 10 iterations of 2 second sleep
    SpamContext="Login"
    TotalWait=0

    # Wait for user to sign on then get Xserver access for xrandr calls
    UserName=""
    while [[ $UserName == "" ]]; do

        # Find UserName currently logged in.
        UserName="$(who -u | grep -F '(:0)' | head -n 1 | awk '{print $1}')"
        [[ $UserName != "" ]] && break

        sleep "$SpamLength"
        TotalWait=$(( TotalWait + SpamLength ))
    done

    if [[ $TotalWait != "0" ]] ; then
        log "Waited $TotalWait seconds for $UserName to login."
        xhost local:root
        export XAUTHORITY="/home/$UserName/.Xauthority"
    fi

} # WaitForSignOn


LastVolume=0
CurrVolume=0


TenMinuteSpam () {

    # If TV not powered up Spam user for 10 minutes that 'tvpowered' is running
    # and will shut down / suspend system

    WaitForSignOn   # Might be called by root during boot before user signed on.

    Cnt=0
    while : ; do

        if GetPowerStatus ; then
            log "TV is powered on. 'tvpowered' is now waiting for TV to power off."
            break
        else
            # Spam user every 60 seconds
            (( $(( Cnt % 20 )) == 0 )) && \
                notify-send --urgency=critical "tvpowered" \
                    -h string:x-canonical-private-synchronous:startup \
                    --icon=/usr/share/icons/gnome/48x48/devices/display.png \
                    "TV not communicating.\n Checking TV again..."
        fi
        sleep 3
        (( Cnt++ ))
    done
    
    GetVolume
    LastVolume="$?"
    VolumeBar $LastVolume
    notify-send --urgency=critical "tvpowered" \
        --icon=/usr/share/icons/gnome/48x48/devices/display.png \
        "Fully activated.\n System will $SCTL when TV powered off.  Volume: $LastVolume $Bar"

    adb connect "$ABD_IP"  # Connect to Google TV.
    return 0

} # TenMinuteSpam

###################################
#            MAINLINE             #
###################################

Main () {

    echo "$0: Initialization. Ensuring TV is powered on before starting."
    TenMinuteSpam
    echo "$0: Fully activated. Waiting for TV to powered off and then $SCTL."
    echo "$0: LastVolume: $LastVolume"

    Cnt=0
    FirstTime=true
    VolumeCnt=0             # TV Remote changed volume, so shorter sleep

    while : ; do

        if ! GetPowerStatus; then

            # START FROM ABOVE: 
            # This was causing 2% CPU drain with Network Manager and
            # debus-daemon. So move from above GetPowerStatus to below.

            # If network down then wait for it to come up. 
            #etherup=$(cat /sys/class/net/e*/carrier) # Returns 1 even disconnected
            #wifi_up=$(cat /sys/class/net/w*/carrier)
            #if [[ $etherup <> "1" && $wifi_up <> "1" ]] ; then
            state=$(nmcli -f STATE -t g)            # Network manager takes .5 CPU
            if [[ $state == disconnected ]] ; then
                # Spam user every 60 * Cot seconds
                notify-send --urgency=critical "tvpowered" \
                    -h string:x-canonical-private-synchronous:startup \
                    --icon=/usr/share/icons/gnome/48x48/devices/display.png \
                    "Internet not up.\nChecking Ethernet and/or  WiFi state again..."
                sleep $((Cnt * 60))
                (( Cnt++ ))
                continue
            else
                Cnt=0                               # Reset timer for next loop
            fi

            # END FROM ABOVE: If network down then wait for it to come up


            state=$(nmcli -f STATE -t g)        # Network manager takes .5 CPU
            if [[ $state == disconnected ]] ; then
                echo "Unexpected disconnect, aborting suspend."
            else
                log "TV Powered off. 'systemctl $SCTL' being called."
                adb connect "$ABD_IP"  # Connect to Google TV.
                adb shell input keyevent 26  # Google TV to sleep (remote off)
                systemctl "$SCTL"
                # systemctl will suspend. When resuming we hit next line
                log "System powered back up. Checking if TV powered on. '$0'."
                sleep 10                        # Time to wake from suspend
                TenMinuteSpam                   # Wait for network connection
                pictureoff                      # Picture off energy saving
            fi
        fi

        GetVolume
        CurrVolume="$?"
        # echo CurrVolume: $CurrVolume LastVolume: $LastVolume

        if [[ "$CurrVolume" != "$LastVolume" ]] ; then
            # Make volume bar using progress bar methods
            VolumeBar $CurrVolume
            # Ask Ubuntu: https://askubuntu.com/a/871207/307523
            notify-send --urgency=critical "tvpowered" \
                -h string:x-canonical-private-synchronous:volume \
                --icon=/usr/share/icons/gnome/48x48/devices/audio-speakers.png \
                "Volume: $CurrVolume $Bar"
            LastVolume=$CurrVolume
            VolumeCnt=100  # For 1 second, faster checks for volume change
            # TODO: Process VolumeCnt internally in loop instead of larger loop
        fi

        if [[ $VolumeCnt > 0 ]]; then
            (( VolumeCnt-- ))
            SleepTime=.01
        else
            SleepTime=.75
        fi

        sleep $SleepTime

        # Next iteration
        FirstTime=false
    done

    exit 0

} # Main

Main "$@"

Summary

I was inspired by OP's question and never realized how cumbersome and time-consuming my end of day suspend process used to be:

  1. Find where the cursor is on on one of three monitors
  2. Navigate to top right of whichever monitor and left click Cog menu
  3. Pull mouse down to suspend option
  4. Click suspend (being careful not to click shutdown next to it!)
  5. Power off Sony TV
  6. Power off Toshiba TV

tvpowered has eliminated time consuming steps 1. through 4.

EDIT: A website was made to document tvpowered


Bonus - Turn of Light Behind TV

For nighttime viewing, there is a light behind the TV. Whenever the laptop goes to sleep, it first shuts off the light.

Create the script /etc/NetworkManager/dispatcher.d/pre-down.d/smartplug_off and place into it:

#!/bin/bash

# NAME: smartplug_off
# PATH: /etc/NetworkManager/dispatcher.d/pre-down.d
# DESC: Turn off smartplug light power for TV light
# DATE: March 7, 2020.

# CALL: Called by Network Manager before going down. Network manager in turn
#       is called by systemd during suspend/hibernate/shutdown

# NOTE: myisp.sh and hs100.sh must be installed for hs100 tp-link power plug.
#       https://developer.gnome.org/NetworkManager/stable/NetworkManager.html

PlugName="192.168.0.15"

status=$(hs100.sh -i "$PlugName" check | cut -f2)
if [ $status == "OFF" ] ; then
    : # Nothing to do already off
elif [ $status == "ON" ] ; then
    hs100.sh -i "$PlugName" off
else
    echo Error hs100.sh not responding check connection and IP "$PlugName".
fi
0

I have a laptop by my television that I access with a wireless keyboard/touchpad device. I also keep the lid closed as well.

What I did is add a simple gnome extension called Gnome-Shutdown-Button. You can find a ton of these extensions at https://extensions.gnome.org/

It opens a dialogue that says "shutting down in 30 seconds" (it might be less) and offers a second option to shut down now.

1
  • Out of all the "mouse only" answers this is probably the best way. But you don't actually have a link to the application, just a link to all the applications in that world? Jun 11, 2020 at 19:46
-1

in terminal shutdown now do the trick for me

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .