Bagaimana saya memanggil gnome-sesi-berhenti dengan hitung mundur dari Unity?

13

Untuk dapat mematikan dengan pintasan keyboard, kita dapat menetapkan gnome-session-quit ---power-offpintasan khusus.

Dalam Unity ini akan mengarah ke dialog berikut:

masukkan deskripsi gambar di sini

Maka kita perlu setidaknya dua penekanan tombol untuk akhirnya mematikan sistem kita. Ini agak tidak nyaman dan saya lebih suka dialog shutdown lama ketika Anda bisa mematikan dengan hanya menekan Returnatau membiarkannya menunggu hitungan mundur default 60 detik.

Saat memanggil gnome-session-quit --poweroffdari sesi kilas balik sesi GNOME pada sistem yang sama (14,04 LTS) dialog lama termasuk hitungan mundurnya kembali:

masukkan deskripsi gambar di sini

Jadi kita tahu itu ada di suatu tempat.

Apakah ada cara untuk memanggil dialog lama ini saat menjalankan sesi Unity?

Takkat
sumber
Apakah satu kesatuan tidak memiliki timer tersembunyi, sehingga tidak mati setelah 60 detik?
Tim
askubuntu.com/questions/14794/… mungkin membantu
Tim
Untuk keduanya: masalahnya dengan dialog baru adalah, bahwa tampaknya menunggu pilihan pengguna untuk apa yang harus dilakukan ...: /
Takkat
2
@Erger Jendela milik Session Manager (saya menjalankan skrip latar belakang untuk menulis properti jendela baru ke file). Masalahnya adalah ia berperilaku berbeda, tergantung pada manajer jendela.
Jacob Vlijm
1
@JacobVlijm: ya itu yang bisa saya lihat juga ... ternyata polling WM dan kemudian memanggil ini atau itu rutin tetapi saya tidak menemukan cara untuk memaksakan ini.
Takkat

Jawaban:

10

Berikut ini skrip untuk meniru perilaku yang diinginkan. Harus dijalankan seperti halnya sudo. Dapat diikat ke pintasan keyboard (dengan penambahan awal shutdownperintah ke file sudoers untuk memungkinkan berjalan tanpa kata sandi ). Sederhana, ringkas, dan melakukan pekerjaan.

#!/bin/bash
# Date: June 11,2015
# Author: Serg Kolo
# Description: a script to emulate
# behavior of GNOME session flashback
# shutdown dialog

# Tell ubuntu to shutdown in 1 min
shutdown -P +1 &
# Show the dialog
zenity --question --text="Shutdown now ? Automatic shutdown in 60 seconds" --ok-label="DOIT" 
# If user clicks DOIT, then cancel the old 
# shutdown call that has countdown,
# (because only one shutdown command can be run at a time), and
# tell ubuntu to shutdown immediately
# otherwise - cancel it
if [ $? -eq 0 ];then
        shutdown -c
        shutdown -P now
else
        shutdown -c
fi

Pembaruan: 14 Juni

Seperti yang disarankan oleh Takkat, berikut ini skrip yang menggunakan opsi --timer dan dbus zenity untuk mencapai perilaku yang sama tanpa perlu akses sudo:

#!/bin/bash
# Date: June 14,2015
# Author: Serg Kolo
# Description: a script to emulate
# behavior of GNOME session flashback
# shutdown dialog
# version #2

zenity --question --text="Shutdown now ? Autoshutdown in 60 seconds" \
    --cancel-label="DOIT" --ok-label="NOPE" --timeout=60 ||  
  dbus-send --system --print-reply --dest=org.freedesktop.login1 \
    /org/freedesktop/login1 "org.freedesktop.login1.Manager.PowerOff" boolean:true

Ide dasar di sini adalah opsi batas waktu zenity keluar dengan kode lebih besar dari 0, yang biasanya berarti perintah gagal. Jadi dengan memperlakukan opsi pembatalan zenity dan batas waktu sebagai kondisi yang memungkinkan shutdown, kami menggunakan operator ATAU ( ||) untuk mematikan hanya jika pengguna mengklik tombol batal (dilabeli sebagai "DOIT") atau waktu dialog habis.

Variasi lain untuk meningkatkan pengalaman pengguna dapat dilakukan dengan yad(perlu diinstal terlebih dahulu dengan perintah ini sudo apt-add-repository ppa:webupd8team/y-ppa-manager;sudo apt-get update; sudo apg-get install yad). Variasi ini menggunakan bilah progres untuk memberi tahu pengguna berapa banyak waktu yang tersisa

    #!/bin/bash
    yad --auto-close --sticky --on-top --skip-taskbar --center \
  --text 'Shutdown now ? Autoshutdown in 60 seconds.' \
  --button="gtk-ok:1" --button="gtk-close:0" --image=dialog-question \ 
--title 'Shutdown' --timeout=60 --timeout-indicator=top || 
dbus-send --system --print-reply --dest=org.freedesktop.login1 \
/org/freedesktop/login1 "org.freedesktop.login1.Manager.PowerOff" boolean:true

Versi lain yang mungkin, memperhitungkan bahwa jika Anda mengubah label tombol ok zenity, tombol yang disorot secara default mungkin atau mungkin bukan tombol ok.

zenity --question --timeout 10 --text="Automatic shutdown in 10 seconds"
if [[ $? -eq 1 ]] ; then
    # user clicked Cancel
    exit 
else
    dbus-send --system --print-reply --dest=org.freedesktop.login1 /org/freedesktop/login1 "org.freedesktop.login1.Manager.PowerOff" boolean:true
fi

Skrip mematikan sistem pada setiap pengembalian yang bukan 0. Jika skrip habis, nilai pengembalian dari 1 atau 5 memberi tahu skrip untuk menjalankan elsebagian

Sergiy Kolodyazhnyy
sumber
Bekerja seperti pesona saat dijalankan dengan sudo atau memungkinkan pengguna non-root untuk shutdown. Saya lebih suka tidak melakukan itu. Izinkan saya menyarankan suntingan berikut untuk mengaktifkan skrip Anda dijalankan oleh pengguna fana: 1. Gunakan dbus untuk poweroff seperti yang disarankan dalam jawaban ini 2. Gunakan zenity --timeouttimer inbuilt. Dengan ini kita tidak perlu membatalkan / memulai kembali shutdown nanti.
Takkat
@Takkat menambahkan skrip lain yang menggunakan saran Anda. Harap tinjau
Sergiy Kolodyazhnyy
Memang memang shutdown tanpa password root tetapi tombol OK / DOIT tidak dipilih secara default untuk shutdown langsung dengan kunci RETURN. Kami menggunakan skrip serupa dengan if [[ $? -eq 1 ]] ; then exit \else dbus...kondisi yang melakukan itu. Jelas tampaknya tidak ada cara untuk memanggil pembantu logout lama ...
Takkat
Tambahkan perintah untuk menginstal yad;)
AB
Seandainya saya bisa membagi hadiah untuk kedua jawaban. Sangat sulit untuk memutuskan di sini setelah memiliki dua jawaban yang sama hebatnya. Akhirnya saya memberikannya kepada Yakub karena jawabannya tampaknya sedikit lebih fleksibel. Tapi skrip Anda melakukan tugasnya dengan luar biasa, dan itu sangat sederhana. Saya akan menandainya sebagai diterima sebagai gantinya agar muncul sebagai jawaban teratas. Saya berharap ini akan mendapatkan lebih banyak suara dari waktu ke waktu dengan ini.
Takkat
6

Tidak secara harfiah apa yang Anda minta, tetapi setidaknya solusi (efektif) yang sebanding adalah dengan meletakkan script di bawah ini di bawah tombol pintas.

Apa yang dilakukannya

Saat tombol pintas digunakan:

  • yang gnome-session-quit --power-offperintah dijalankan
  • mouse dipindahkan ke tombol "tutup" yang sesuai, secara efektif membuat tombol shutdown telah dipilih sebelumnya:

    masukkan deskripsi gambar di sini

Kemudian:

  • Jika pengguna menekan Enter, sistem dimatikan
  • Jika pengguna tidak melakukan apa-apa, sistem menunggu selama 30 detik (atau periode waktu lain yang ingin Anda tetapkan) dan dimatikan.
  • Jika pengguna menggerakkan mouse selama 30 detik, prosedur dihentikan

Naskah

#!/usr/bin/env python3
import subprocess
import time

#--- set the location of the close button x, y
q_loc = [1050, 525]
#--- set the time to wait before shutdown
countdown = 30

subprocess.Popen(["gnome-session-quit", "--power-off"])
# for slower systems, set a longer break, on faster systems, can be shorter:
time.sleep(0.4)
subprocess.Popen(["xdotool", "mousemove", str(q_loc[0]), str(q_loc[1])])

coords1 = q_loc
t = 0

while True:
    time.sleep(1)
    cmd = "xdotool", "getmouselocation"
    currloc = subprocess.check_output(cmd).decode("utf-8").split()[:2]
    coords2 = [int(n.split(":")[1]) for n in currloc]
    if coords2 != coords1:
        break
    else:
        if t >= countdown:
            subprocess.Popen(["xdotool", "key", "KP_Enter"])
            break
    t += 1

Cara Penggunaan

Saya cukup yakin Anda tahu cara menggunakannya, tapi di sini kita pergi untuk alasan habbit:

  1. Script digunakan xdotool

    sudo apt-get install xdotool
    
  2. Salin skrip ke file kosong, simpan sebagai run_close.py

  3. Di bagian kepala, atur lokasi layar tombol mati di jendela dekat (tebakan pertama saya benar):

    #--- set the location of the close button x, y
    q_loc = [1050, 525]
    

    dan waktu untuk menunggu sebelum dimatikan:

    #--- set the time to wait before shutdown
    countdown = 30
    
  4. Tes-jalankan dengan perintah:

    python3 /path/to/run_close.py
    

    Uji dengan semua opsi: menekan Enteruntuk segera dimatikan, shutdown tanpa pengawasan dan hancurkan prosedur dengan mouse-move

  5. Jika semua berfungsi dengan baik, tambahkan ke tombol pintasan: pilih: Pengaturan Sistem> "Keyboard"> "Pintasan"> "Pintasan Khusus". Klik "+" dan tambahkan perintah:

     python3 /path/to/run_close.py
    

EDIT

Di bawah versi skrip yang tidak memerlukan pengaturan tambahan. Ini menghitung koordinat tombol keluar, tidak peduli apa resolusi layarnya.

Pengaturannya hampir sama, tetapi [3.]bisa dilewati.

#!/usr/bin/env python3
import subprocess
import time

#--- set the time to wait before shutdown
countdown = 30

def get_qloc():
    xr = subprocess.check_output(["xrandr"]).decode("utf-8").split()
    scrs = [s.split("+") for s in xr if all([s.count("x") == 1, s.count("+") == 2])]
    center = [int(int(s)/2) for s in [scr[0] for scr in scrs if scr[1] == "0"][0].split("x")]
    return [center[0] + 250, center[1]]

q_loc = get_qloc()

subprocess.Popen(["gnome-session-quit", "--power-off"])
# for slower systems, set a longer break, on faster systems, can be shorter:
time.sleep(0.4)
subprocess.Popen(["xdotool", "mousemove", str(q_loc[0]), str(q_loc[1])])

coords1 = q_loc
t = 0

while True:
    time.sleep(1)
    cmd = "xdotool", "getmouselocation"
    currloc = subprocess.check_output(cmd).decode("utf-8").split()[:2]
    coords2 = [int(n.split(":")[1]) for n in currloc]
    if coords2 != coords1:
        break
    else:
        if t >= countdown:
            subprocess.Popen(["xdotool", "key", "KP_Enter"])
            break
    t += 1

Penjelasan

Ukuran jendela Session Manager untuk menutup sistem selalu terpusat dan berukuran tetap (absolut), tidak tergantung pada resolusi layar. Oleh karena itu posisi relatif ke tengah layar adalah faktor konstan.

Yang perlu kita lakukan adalah membaca resolusi layar dan menghitung posisi tombol dari sana.

Fungsi yang diterapkan ( get_qloc()) menghitung resolusi layar kiri , karena di situlah dialog akan muncul.

Catatan

Waktu, yang diatur dalam garis time.sleep(0.4)diatur untuk sistem yang relatif lambat, untuk memastikan mouse digerakkan setelah jendela dimatikan muncul. Pada sistem yang lebih cepat, bisa lebih pendek, pada sistem yang lebih lambat (seperti mungkin VM) mungkin perlu diatur lebih lama.

Yakub Vlijm
sumber
@Takkat Tetap, versi ini harus bekerja pada resolusi apa pun.
Jacob Vlijm
Bagus! Ia bekerja dengan sempurna di VM saya juga.
Takkat