ฉันจะเรียก gnome-session-quit โดยนับถอยหลังจาก Unity ได้อย่างไร


13

เพื่อให้สามารถปิดระบบด้วยแป้นพิมพ์ลัดเราสามารถกำหนดให้gnome-session-quit ---power-offกับทางลัดที่กำหนดเอง

ในความสามัคคีสิ่งนี้จะนำไปสู่กล่องโต้ตอบต่อไปนี้:

ป้อนคำอธิบายรูปภาพที่นี่

จากนั้นเราต้องการการกดแป้นอย่างน้อยสองครั้งเพื่อปิดระบบของเราในที่สุด ค่อนข้างจะไม่สะดวกและฉันต้องการให้กล่องโต้ตอบการปิดเครื่องเก่าเมื่อคุณสามารถปิดเครื่องโดยกดReturnหรือปล่อยให้มันรอการนับถอยหลังเริ่มต้น 60 วินาที

เมื่อโทรgnome-session-quit --poweroffจากเซสชันย้อนหลังเซสชัน GNOMEในระบบเดียวกัน (14.04 LTS) กล่องโต้ตอบเก่ารวมถึงการนับถอยหลังจะกลับมา:

ป้อนคำอธิบายรูปภาพที่นี่

ดังนั้นเราจึงรู้ว่ามันอาศัยอยู่ที่ไหนซักแห่ง

มีวิธีใดที่จะเรียกใช้กล่องโต้ตอบเก่านี้เมื่อใช้งานเซสชัน Unity หรือไม่


เอกภาพหนึ่งไม่มีตัวจับเวลาที่ซ่อนอยู่หรือไม่ดังนั้นจึงปิดหลังจาก 60 วินาทีหรือไม่
ทิม

askubuntu.com/questions/14794/…อาจช่วยได้
ทิม

สำหรับทั้งคู่: สิ่งที่มีไดอะล็อกใหม่ก็คือดูเหมือนว่าจะรอให้ผู้ใช้เลือกสิ่งที่ต้องทำ ... : /
Takkat

2
@Serg หน้าต่างเป็นของ Session Manager (ฉันใช้งานสคริปต์พื้นหลังเพื่อเขียนคุณสมบัติของหน้าต่างใหม่ไปยังไฟล์) ปัญหาคือมันทำงานแตกต่างกันขึ้นอยู่กับตัวจัดการหน้าต่าง
Jacob Vlijm

1
@JacobVlijm: ใช่นั่นคือสิ่งที่ฉันเห็นด้วย ... มันเห็นได้ชัดว่าสำรวจความคิดเห็น WM แล้วเรียกสิ่งนี้หรือกิจวัตรประจำวันนั้น แต่ฉันไม่พบวิธีที่จะบังคับสิ่งนี้
Takkat

คำตอบ:


10

นี่คือสคริปต์เพื่อเลียนแบบพฤติกรรมที่ต้องการ sudoจะต้องวิ่งเช่นเดียวกับ สามารถเชื่อมโยงกับแป้นพิมพ์ลัด (ด้วยการเพิ่มshutdownคำสั่งเบื้องต้นไปยังไฟล์ sudoers เพื่อให้สามารถเรียกใช้รหัสผ่านได้ ) ง่ายกระชับและทำงาน

#!/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

อัปเดต: 14 มิถุนายน

ตามที่ Takkat แนะนำนี่คือสคริปต์ที่ใช้ตัวเลือก --timer ของ zenity และ dbus เพื่อให้ได้พฤติกรรมเดียวกันโดยไม่จำเป็นต้องเข้าถึง 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

แนวคิดพื้นฐานที่นี่คือตัวเลือกการหมดเวลาของ zenity ออกจากด้วยรหัสที่มากกว่า 0 ซึ่งโดยทั่วไปหมายถึงคำสั่งล้มเหลว ดังนั้นโดยการใช้ตัวเลือกการยกเลิกและการหมดเวลาของ Zenity ตามเงื่อนไขที่จะอนุญาตให้ปิดระบบเราจะใช้ตัวดำเนินการ OR ( ||) เพื่อปิดเฉพาะเมื่อผู้ใช้คลิกปุ่มยกเลิก (ระบุว่า "DOIT") หรือกล่องโต้ตอบหมดเวลา

รูปแบบอื่นเพื่อปรับปรุงประสบการณ์ผู้ใช้สามารถทำได้ด้วยyad(ต้องติดตั้งก่อนด้วยคำสั่งเหล่านี้sudo apt-add-repository ppa:webupd8team/y-ppa-manager;sudo apt-get update; sudo apg-get install yad) ชุดรูปแบบนี้ใช้แถบความคืบหน้าเพื่อให้ผู้ใช้ทราบว่าเหลือเวลาอีกเท่าใด

    #!/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

อีกรุ่นที่เป็นไปได้คำนึงถึงว่าหากคุณเปลี่ยนป้ายปุ่มตกลงของ zenity ปุ่มที่เน้นโดยค่าเริ่มต้นอาจเป็นหรือไม่เป็นปุ่มตกลงก็ได้

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

สคริปต์จะปิดระบบเมื่อการส่งคืนใด ๆ ที่ไม่ใช่ 0 หากสคริปต์หมดเวลาค่าส่งคืนของ 1 หรือ 5 จะบอกให้สคริปต์ดำเนินการelseส่วนนั้น


ทำงานได้อย่างมีเสน่ห์เมื่อทำงานด้วย sudo หรืออนุญาตให้ผู้ใช้ที่ไม่ใช่รูทปิด ฉันไม่อยากทำอย่างนั้น ฉันขอแนะนำการแก้ไขต่อไปนี้เพื่อให้สคริปต์ของคุณถูกเรียกใช้โดยผู้ใช้ที่เป็นมนุษย์: 1.ใช้ dbus สำหรับ poweroff ตามที่แนะนำในคำตอบนี้ 2.ใช้zenity --timeoutตัวจับเวลา inbuilt จากนี้เราจะไม่ต้องยกเลิก / รีสตาร์ทการปิดในภายหลัง
Takkat

@Takkat เพิ่มสคริปต์อื่นที่ใช้คำแนะนำของคุณ โปรดตรวจสอบ
Sergiy Kolodyazhnyy

มันจะปิดระบบโดยไม่ต้องใช้รหัสผ่านรูท แต่ปุ่ม OK / DOIT จะไม่ถูกเลือกโดยค่าเริ่มต้นสำหรับการปิดระบบทันทีด้วยปุ่ม RETURN เราใช้สคริปต์ที่คล้ายกันกับif [[ $? -eq 1 ]] ; then exit \else dbus...เงื่อนไขซึ่งทำเช่นนั้น เห็นได้ชัดว่าดูเหมือนจะไม่มีทางที่จะเรียกผู้ช่วยออกจากระบบเก่า ...
Takkat

เพิ่มคำสั่งเพื่อติดตั้ง yad;)
AB

หวังว่าฉันจะแบ่งเงินรางวัลให้กับคำตอบทั้งสองได้ มันยากมากที่จะตัดสินใจที่นี่หลังจากมีคำตอบที่ดีเยี่ยมสองข้อเช่นกัน ในที่สุดฉันก็ให้ยาโคบเพราะคำตอบของเขาดูเหมือนจะมีความหลากหลายมากกว่า แต่สคริปต์ของคุณทำงานได้อย่างยอดเยี่ยมและมันก็ง่ายมาก ฉันจะทำเครื่องหมายว่ายอมรับแล้วเพื่อให้ปรากฏเป็นคำตอบอันดับต้น ๆ ฉันหวังว่ามันจะได้รับคะแนนเสียงมากขึ้นเมื่อเวลาผ่านไป
Takkat

6

ไม่ใช่สิ่งที่คุณขออย่างแท้จริงแต่อย่างน้อยโซลูชันที่เทียบเคียงได้อย่างมีประสิทธิภาพจะวางสคริปต์ด้านล่างไว้ใต้คีย์ลัด

มันทำอะไร

เมื่อใช้คีย์ลัด:

  • gnome-session-quit --power-offคำสั่งเรียก
  • เมาส์ถูกย้ายไปยังปุ่ม "ปิด" ที่สอดคล้องกันทำให้การเลือกปิดปุ่มได้อย่างมีประสิทธิภาพ :

    ป้อนคำอธิบายรูปภาพที่นี่

แล้ว:

  • หากผู้ใช้กดEnterระบบจะปิด
  • หากผู้ใช้ไม่ทำอะไรเลยระบบจะรอเป็นเวลา 30 วินาที (หรือช่วงเวลาอื่นที่คุณต้องการตั้งค่า) และปิดตัวลง
  • หากผู้ใช้เลื่อนเมาส์ระหว่าง 30 วินาทีขั้นตอนจะหยุด

บท

#!/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

วิธีใช้

ฉันค่อนข้างแน่ใจว่าคุณรู้วิธีการใช้งาน แต่ที่นี่เราไปด้วยเหตุผล habbit:

  1. สคริปต์ใช้ xdotool

    sudo apt-get install xdotool
    
  2. คัดลอกสคริปต์ไปยังไฟล์เปล่าบันทึกเป็น run_close.py

  3. ในส่วนหัวให้ตั้งตำแหน่งของหน้าจอของปุ่มปิดเครื่องในหน้าต่างปิด (เดาแรกของฉันถูกต้อง):

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

    และเวลาที่จะรอก่อนที่จะปิดตัวลงโดยไม่ตั้งใจ:

    #--- set the time to wait before shutdown
    countdown = 30
    
  4. ทดสอบเรียกใช้โดยคำสั่ง:

    python3 /path/to/run_close.py
    

    ทดสอบด้วยตัวเลือกทั้งหมด: กดEnterเพื่อปิดเครื่องทันทีปิดเครื่องโดยไม่ต้องใส่เครื่องและทำตามขั้นตอนโดยเลื่อนเม้าส์

  5. หากใช้งานได้ดีให้เพิ่มลงในคีย์ลัด: เลือก: การตั้งค่าระบบ> "คีย์บอร์ด"> "ทางลัด"> "ทางลัดที่กำหนดเอง" คลิกที่ "+" และเพิ่มคำสั่ง:

     python3 /path/to/run_close.py
    

แก้ไข

ด้านล่างเป็นเวอร์ชันของสคริปต์ที่ไม่ต้องการการตั้งค่าเพิ่มเติมใด ๆ มันจะคำนวณพิกัดของปุ่มออกไม่ว่าอะไรจะเป็นความละเอียดของหน้าจอ

การตั้งค่าค่อนข้างเหมือนกัน แต่[3.]สามารถข้ามได้

#!/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

คำอธิบาย

ขนาดของหน้าต่างตัวจัดการเซสชันเพื่อปิดระบบจะอยู่กึ่งกลางเสมอและมีขนาดคงที่ (แน่นอน) ขึ้นอยู่กับความละเอียดของหน้าจอ ดังนั้นตำแหน่งที่สัมพันธ์กับศูนย์กลางของหน้าจอเป็นปัจจัยคงที่

สิ่งที่เราต้องทำก็คืออ่านความละเอียดของหน้าจอและคำนวณตำแหน่งของปุ่มจากตรงนั้น

ฟังก์ชั่นที่ใช้ ( get_qloc()) คำนวณความละเอียดของหน้าจอด้านซ้ายเนื่องจากเป็นฟังก์ชั่นการสนทนาที่ปรากฏขึ้น

บันทึก

เวลาที่ตั้งไว้ในสายtime.sleep(0.4)ถูกตั้งค่าไว้สำหรับระบบที่ค่อนข้างช้าเพื่อให้แน่ใจว่าเมาส์จะถูกย้ายหลังจากหน้าต่างปิดการทำงานปรากฏขึ้น สำหรับระบบที่เร็วกว่านั้นสามารถสั้นลงได้บนระบบที่ช้ากว่า (เช่น VM) ซึ่งอาจจำเป็นต้องตั้งค่าให้นานขึ้น


@ Takakat แก้ไขแล้วเวอร์ชั่นนี้ควรใช้กับความละเอียดใด ๆ
Jacob Vlijm

ที่ดี! มันทำงานได้อย่างไม่มีที่ติบน VM ของฉันด้วย
Takkat
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.