ฉันแค่ต้องการให้โทรเลขทำงานและฉันได้เพิ่มลงในแอปเริ่มต้น ประเด็นคือฉันต้องการให้มันลดลง คำสั่งใด ๆ
ฉันแค่ต้องการให้โทรเลขทำงานและฉันได้เพิ่มลงในแอปเริ่มต้น ประเด็นคือฉันต้องการให้มันลดลง คำสั่งใด ๆ
คำตอบ:
การเริ่มต้นแอปพลิเคชันด้วยวิธีที่ย่อเล็กสุดใช้สองคำสั่ง:
ดังนั้นคำสั่งหรือสคริปต์จะต้อง "ฉลาด"; คำสั่งที่สองควรรอให้หน้าต่างแอปพลิเคชันปรากฏขึ้นจริง
สคริปต์ด้านล่างทำเช่นนั้นและสามารถใช้เป็นโซลูชันทั่วไปในการเริ่มต้นแอปพลิเคชันในแบบที่ย่อเล็กสุด เพียงเรียกใช้ในรูปแบบของไวยากรณ์:
<script> <command_to_run_the_application> <window_name>
#!/usr/bin/env python3
import subprocess
import sys
import time
subprocess.Popen(["/bin/bash", "-c", sys.argv[1]])
windowname = sys.argv[2]
def read_wlist(w_name):
try:
l = subprocess.check_output(["wmctrl", "-l"]).decode("utf-8").splitlines()
return [w.split()[0] for w in l if w_name in w][0]
except (IndexError, subprocess.CalledProcessError):
return None
t = 0
while t < 30:
window = read_wlist(windowname)
time.sleep(0.1)
if window != None:
subprocess.Popen(["xdotool", "windowminimize", window])
break
time.sleep(1)
t += 1
สคริปต์ต้องการทั้งwmctrl
และxdotool
:
sudo apt-get install wmctrl xdotool
แล้ว:
startup_minimizd.py
ทดสอบสคริปต์ด้วยgedit
คำสั่ง(เช่น) :
python3 /path/to/startup_minimizd.py gedit gedit
Startup Applications
wmctrl
) สำหรับ windows ตั้งชื่อตามอาร์กิวเมนต์ที่สองของคุณxdotool
เพื่อป้องกันการวนซ้ำไม่สิ้นสุดหากหน้าต่างอาจไม่ปรากฏขึ้นด้วยเหตุผลบางอย่างสคริปต์จะดำเนินการ จำกัด เวลา 30 วินาทีเพื่อให้หน้าต่างปรากฏขึ้นไม่จำเป็นต้องพูดถึงว่าคุณสามารถใช้สคริปต์สำหรับหลาย ๆ แอปพลิเคชันได้ในครั้งเดียวเนื่องจากคุณรันสคริปต์ด้วยอาร์กิวเมนต์ที่อยู่นอกสคริปต์
หากชื่อหน้าต่างไม่แน่ใจหรือตัวแปรหรือมีความเสี่ยงของการปะทะกันของชื่อในชื่อของหน้าต่างการใช้pid
เป็นวิธีที่เชื่อถือได้มากขึ้นในการใช้
สคริปต์ด้านล่างนี้ขึ้นอยู่กับการใช้ pid ของแอปพลิเคชันเช่นเดียวกับในเอาต์พุตของทั้งสองwmctrl -lp
และps -ef
และ
การตั้งค่าค่อนข้างเหมือนกัน แต่ไม่จำเป็นต้องตั้งชื่อหน้าต่างในรุ่นนี้ดังนั้นคำสั่งในการรันคือ:
python3 /path/to/startup_minimizd.py <command_to_run_application>
เช่นเดียวกับสคริปต์แรกมันต้องการทั้งสองอย่างwmctrl
และxdotool
#!/usr/bin/env python3
import subprocess
import sys
import time
command = sys.argv[1]
command_check = command.split("/")[-1]
subprocess.Popen(["/bin/bash", "-c", command])
t = 1
while t < 30:
try:
w_list = [l.split() for l in subprocess.check_output(["wmctrl", "-lp"]).decode("utf-8").splitlines()]
proc = subprocess.check_output(["pgrep", "-f", command_check]).decode("utf-8").strip().split()
match = sum([[l[0] for l in w_list if p in l] for p in proc], [])
subprocess.Popen(["xdotool", "windowminimize", match[0]])
break
except (IndexError, subprocess.CalledProcessError):
pass
t += 1
time.sleep(1)
แม้ว่าโดยทั่วไปแล้วเวอร์ชันที่สองควรมีความน่าเชื่อถือมากกว่าในกรณีที่แอปพลิเคชันเริ่มต้นด้วยสคริปต์ตัวตัดคำสั่ง pid ของคำสั่งจะแตกต่างจากแอปพลิเคชันที่ถูกเรียกใช้ในที่สุด
ในกรณีเช่นนี้ฉันขอแนะนำให้ใช้สคริปต์แรก
ตามที่ร้องขอในความคิดเห็นด้านล่างเวอร์ชันสร้างขึ้นเป็นพิเศษสำหรับการเริ่มต้นใช้งาน STEAM ย่อเล็กสุด
ปรากฎว่าSteam
ทำงานค่อนข้างแตกต่างจากแอปพลิเคชัน "ปกติ":
Steam
ไม่ได้ทำงานเพียงหนึ่ง pid แต่ไม่น้อยกว่า (ในการทดสอบของฉัน) แปด!Steam
ทำงานเมื่อเริ่มต้นด้วยหน้าต่างอย่างน้อยสองหน้าต่าง (หน้าต่างเดียวเหมือน splash-) แต่บางครั้งหน้าต่างข้อความเพิ่มเติมจะปรากฏขึ้นpid 0
ซึ่งเป็นปัญหาในสคริปต์เหมือนเดิมพฤติกรรมที่พิเศษของการSteam
ขอสคริปต์รุ่นพิเศษซึ่งเพิ่มไว้ด้านล่าง สคริปต์เริ่มทำงานSteam
และในช่วง 12 วินาทีมันจะคอยดูหน้าต่างใหม่ทั้งหมดของหน้าต่างที่เกี่ยวข้องWM_CLASS
โดยตรวจสอบว่ามีการย่อขนาดเล็กสุดหรือไม่ ถ้าไม่สคริปต์จะทำให้แน่ใจว่าพวกเขาจะ
เช่นเดียวกับสคริปต์เดิมนี้หนึ่งในความต้องการwmctrl
และxdotool
มีการติดตั้ง
#!/usr/bin/env python3
import subprocess
import time
command = "steam"
subprocess.Popen(["/bin/bash", "-c", command])
def get(cmd):
return subprocess.check_output(cmd).decode("utf-8").strip()
t = 0
while t < 12:
try:
w_list = [l.split()[0] for l in get(["wmctrl", "-l"]).splitlines()]
for w in w_list:
data = get(["xprop", "-id", w])
if all(["Steam" in data, not "_NET_WM_STATE_HIDDEN" in data]):
subprocess.Popen(["xdotool", "windowminimize", w])
except (IndexError, subprocess.CalledProcessError):
pass
t += 1
time.sleep(1)
runsteam_minimized.py
เรียกใช้โดยคำสั่ง:
python3 /path/to/runsteam_minimized.py
except:
เพื่อส่งคืนไม่มี อาจดีกว่าปล่อยให้มันล้มเหลวเพื่อให้คุณเห็นสิ่งที่ล้มเหลว มิเช่นนั้นอาจทำลายสาเหตุที่แตกต่างกันและจะผ่านไปโดยไม่ตั้งใจ
subprocess.CalledProcesError
(เนื่องจาก buggy wmctrl
) และIndexError
(ข้อยกเว้นปกติ) จะแก้ไขในหนึ่งนาที :) ขอบคุณที่พูดถึง
เป็นการดีที่จะให้สคริปต์ที่กำหนดโดยผู้ใช้ 72216 และ Sergey เป็นวิธีแก้ไขปัญหาทั่วไป แต่บางครั้งแอปพลิเคชันที่คุณต้องการเริ่มต้นย่อให้เล็กสุดก็มีสวิตช์ที่จะทำสิ่งที่คุณต้องการ
นี่คือตัวอย่างเล็ก ๆ น้อย ๆ ที่มีสตริงคำสั่งของโปรแกรมเริ่มต้นที่เกี่ยวข้อง:
-startintray
ตัวเลือก:<path-to-Telegram>/Telegram -startintray
-silent
ตัวเลือก:/usr/bin/steam %U -silent
--minimized
ตัวเลือก:/usr/bin/transmission-gtk --minimized
ใน Unity แอปพลิเคชันเหล่านี้จะย่อขนาดเป็นไอคอนในแถบเมนูด้านบนแทนที่จะเป็นไอคอนบนตัวเรียกใช้งานแม้ว่าไอคอนตัวเรียกใช้ปกติจะยังคงปรากฏขึ้นเมื่อคุณเริ่มใช้แอปพลิเคชัน แอปพลิเคชันอื่นอาจทำงานแตกต่างกัน
ฉันใช้สคริปต์ของยาโคบแล้วปรับเปลี่ยนเล็กน้อยเพื่อให้เป็นสากลมากขึ้น
#!/usr/bin/python
import os
import subprocess
import sys
import time
import signal
WAIT_TIME = 10
def check_exist(name):
return subprocess.Popen("which "+name,
shell=True,
stdout=subprocess.PIPE
).stdout.read().rstrip("-n")
def killpid(pidlist):
for pid in pidlist:
args = ["xdotool",
"search",
"--any",
"--pid",
pid,
"--name",
"notarealprogramname",
"windowunmap",
"--sync",
"%@"]
subprocess.Popen(args)
def killname(name):
args = ["xdotool",
"search",
"--any",
"--name",
"--class",
"--classname",
name,
"windowunmap",
"--sync",
"%@"]
subprocess.Popen(args)
sys.argv.pop(0)
if check_exist(sys.argv[0]) == "":
sys.exit(1)
if check_exist("xdotool") == "":
sys.stderr.write("xdotool is not installed\n")
sys.exit(1)
if check_exist("wmctrl") == "":
sys.stderr.write("wmctrl is not installed\n")
sys.exit(1)
try:
prog = subprocess.Popen(sys.argv, preexec_fn=os.setsid)
except OSError, e:
sys.exit(1)
time.sleep(WAIT_TIME)
idlist = subprocess.Popen("pgrep -g " + str(prog.pid),
shell=True,
stdout=subprocess.PIPE
).stdout.read().splitlines()
ps1 = os.fork()
if ps1 > 0:
ps2 = os.fork()
if ps1 == 0: # Child 1
os.setpgid(os.getpid(), os.getpid())
killpid(idlist)
sys.exit(0)
elif ps2 == 0: # Child 2
killname(os.path.basename(sys.argv[0]))
sys.exit(0)
elif ps1 > 0 and ps2 > 0: # Parent
time.sleep(WAIT_TIME)
os.killpg(os.getpgid(int(ps1)), signal.SIGTERM)
os.kill(ps2, signal.SIGTERM)
os.waitpid(ps1, 0)
os.waitpid(ps2, 0)
sys.exit(0)
else:
exit(1)
ความแตกต่างที่สำคัญคือ:
ควรตั้งค่า WAIT_TIME ใหญ่พอที่จะอนุญาตให้โปรแกรมแยกกระบวนการย่อย ในคอมพิวเตอร์ของฉันมันก็เพียงพอแล้วสำหรับโปรแกรมขนาดใหญ่เช่น Steam เพิ่มมันถ้าจำเป็น
ส่วนที่เพิ่มเข้าไป
xdotool
ตัวเลือกของตัวเลือกwindowunmap
อาจทำงานได้ดีกับบางแอปพลิเคชั่นและโปรแกรมถาด (เช่นถาดของ linux mint) ดังนั้นนี่เป็นเวอร์ชั่นทางเลือกของสคริปต์สำหรับข้อยกเว้นเหล่านั้น
#!/usr/bin/python
import os
import subprocess
import sys
import time
import signal
WAIT_TIME = 10
def check_exist(name):
return subprocess.Popen("which "+name,
shell=True,
stdout=subprocess.PIPE
).stdout.read().rstrip("-n")
def killpid(pidlist):
for pid in pidlist:
args = ["xdotool",
"search",
"--sync",
"--pid",
pid]
for i in subprocess.Popen(args,
stdout=subprocess.PIPE).\
stdout.read().splitlines():
if i != "":
subprocess.Popen("wmctrl -i -c " +
hex(int(i)), shell=True)
def killname(name):
args = ["xdotool",
"search",
"--sync",
"--any",
"--name",
"--class",
"--classname",
name]
for i in subprocess.Popen(args,
preexec_fn=os.setsid,
stdout=subprocess.PIPE)\
.stdout.read().splitlines():
if i != "":
subprocess.Popen("wmctrl -i -c " + hex(int(i)),
shell=True)
sys.argv.pop(0)
if check_exist(sys.argv[0]) == "":
sys.exit(1)
if check_exist("xdotool") == "":
sys.stderr.write("xdotool is not installed\n")
sys.exit(1)
if check_exist("wmctrl") == "":
sys.stderr.write("wmctrl is not installed\n")
sys.exit(1)
try:
prog = subprocess.Popen(sys.argv, preexec_fn=os.setsid)
except OSError, e:
sys.exit(1)
time.sleep(WAIT_TIME)
idlist = subprocess.Popen("pgrep -g " + str(prog.pid),
shell=True,
stdout=subprocess.PIPE
).stdout.read().splitlines()
ps1 = os.fork()
if ps1 > 0:
ps2 = os.fork()
if ps1 == 0: # Child 1
os.setpgid(os.getpid(), os.getpid())
killpid(idlist)
sys.exit(0)
elif ps2 == 0: # Child 2
killname(os.path.basename(sys.argv[0]))
sys.exit(0)
elif ps1 > 0 and ps2 > 0: # Parent
time.sleep(WAIT_TIME)
os.killpg(os.getpgid(int(ps1)), signal.SIGTERM)
os.kill(ps2, signal.SIGTERM)
os.waitpid(ps1, 0)
os.waitpid(ps2, 0)
sys.exit(0)
else:
exit(1)
startminimized
ฉันบันทึกเป็น startminimized gnome-calendar
แล้วผมก็วิ่ง ปฏิทินเปิดและทำงานต่อไปหรือไม่
WAIT_TIME
ได้ ฉันใช้ความล่าช้า 40 วินาทีสำหรับคอมพิวเตอร์ที่อ่อนแอ นอกจากนี้คุณสามารถลองใช้สคริปต์ที่สองเนื่องจากใช้คำสั่งอื่นเพื่อย่อขนาดแอป
หากโปรแกรมถูกปิดลงในถาดหนึ่งอาจต้องการปิดหน้าต่างโปรแกรมเมื่อเริ่มต้นแทนการย่อเล็กสุด ตัวอย่างหนึ่งของโปรแกรมดังกล่าวคือ Viber ในกรณีนี้เราสามารถใช้สคริปต์ต่อไปนี้start_closed.sh
:
#!/bin/bash
# Check that there is only one input argument
if [[ $# -gt 1 ]]; then
echo "Usage: $0 <program-to-start>"
exit 1
fi
$1 & # Start program passed in first argument
pid=$! # Get PID of last started program
xdotool search --sync --pid $pid | # Wait for window with PID to appear...
xargs wmctrl -i -c # ...and close it
การใช้งาน: <path-to-script> <program-to-start>
xdotool
จะไม่ทำงานอย่างถูกต้องในการติดตั้งด้วย Wayland
ฉันเพิ่งท่องและเจอคำถามนี้ดังนั้นฉันแค่สงสัยว่าระบบปฏิบัติการของคุณคืออะไร สำหรับฉันฉันใช้UBUNTU BUDGIE 18.04 LTSดังนั้นในระบบปฏิบัติการนี้มันง่ายมาก
เพียงไปที่เมนู
จากเมนูไปที่การตั้งค่า Budgie Desktop
และ
จาก Desktop Setting ไปที่ Auto Start
มันจะให้ 2 ตัวเลือกจาก "+" เพิ่ม
1. เพิ่มแอปพลิเคชัน
2. เพิ่มคำสั่ง
โดยการเลือกเพิ่มแอปพลิเคชันทั้งหมดแอปพลิเคชันจะแสดงรายการเลือกแอปพลิเคชันที่คุณต้องการและแอปจะเริ่มเมื่อคุณเริ่มคอมพิวเตอร์และจะถูกย่อให้เล็กสุด
ฉันต้องการโปรแกรมที่ปิดลงในถาดไม่ย่อเล็กสุดและฉันได้ลองสคริปต์ทั้งหมดที่โพสต์ที่นี่โปรแกรมที่ใช้งานได้ใช้ได้กับบางโปรแกรมเท่านั้นและไม่ใช่สำหรับโปรแกรมอื่น ๆ ดังนั้นฉันจึงเขียนโค้ดที่ใช้งานได้ดีกว่ามาก (คุณแทบไม่เห็นหน้าต่างปรากฏขึ้นมีเพียงไอคอนถาดมันดูเป็นเนทิฟ) และใช้งานได้กับทุกโปรแกรมที่ฉันได้ลอง มันขึ้นอยู่กับยาโคบ ด้วยสคริปต์นี้คุณอาจจำเป็นต้องเพิ่มอาร์กิวเมนต์ขึ้นอยู่กับโปรแกรม (ดูด้านล่าง) แต่ทำงานได้ดีสำหรับฉันเสมอด้วยโปรแกรมมากมายมันควรทำงานกับ Steam ด้วย
การใช้งาน:
sudo apt-get install wmctrl xdotool
startup_closed.py
ให้สิทธิ์ในการเรียกใช้แล้วดำเนินการpython3 ./startup_closed.py -c <command to open program>
-splash
หรือ-hide
จากการลองผิดลองถูก ตัวอย่างเช่น: python3 ./startup_closed.py -hide -c teamviewer
หรือpython3 ./startup_closed.py -splash -c slack
./startup_closed.py --help
สคริปต์:
#!/usr/bin/env python3
import subprocess
import sys
import time
import argparse
import random
parser = argparse.ArgumentParser(description='This script executes a command you specify and closes or hides the window/s that opens from it, leaving only the tray icon. Useful to "open closed to tray" a program. If the program does not have a tray icon then it just gets closed. There is no magic solution to achieve this that works for all the programs, so you may need to tweek a couple of arguments to make it work for your program, a couple of trial and error may be required with the arguments -splash and -hide, you probably will not need the others.')
parser.add_argument("-c", type=str, help="The command to open your program. This parameter is required.", required=True)
parser.add_argument("-splash", help="Does not close the first screen detected. Closes the second window detected. Use in programs that opens an independent splash screen. Otherwise the splash screen gets closed and the program cannot start.", action='store_true', default=False)
parser.add_argument("-hide", help="Hides instead of closing, for you is the same but some programs needs this for the tray icon to appear.", action='store_true', default=False)
parser.add_argument("-skip", type=int, default=0, help='Skips the ammount of windows specified. For example if you set -skip 2 then the first 2 windows that appear from the program will not be affected, use it in programs that opens multiple screens and not all must be closed. The -splash argument just increments by 1 this argument.', required=False)
parser.add_argument("-repeat", type=int, default=1, help='The amount of times the window will be closed or hidden. Default = 1. Use it for programs that opens multiple windows to be closed or hidden.', required=False)
parser.add_argument("-delay", type=float, default=10, help="Delay in seconds to wait before running the application, useful at boot to not choke the computer. Default = 10", required=False)
parser.add_argument("-speed", type=float, default=0.02, help="Delay in seconds to wait between closing attempts, multiple frequent attempts are required because the application may be still loading Default = 0.02", required=False)
args = parser.parse_args()
if args.delay > 0:
finalWaitTime = random.randint(args.delay, args.delay * 2);
print(str(args.delay) + " seconds of delay configured, will wait for: " + str(finalWaitTime))
time.sleep(finalWaitTime)
print("waiting finished, running the application command...")
command_check = args.c.split("/")[-1]
subprocess.Popen(["/bin/bash", "-c", args.c])
hasIndependentSplashScreen = args.splash
onlyHide = args.hide
skip = args.skip
repeatAmmount = args.repeat
speed = args.speed
actionsPerformed = 0
lastWindowId = 0
if hasIndependentSplashScreen:
skip += 1
while True:
try:
w_list = [l.split() for l in subprocess.check_output(["wmctrl", "-lp"]).decode("utf-8").splitlines()]
proc = subprocess.check_output(["pgrep", "-f", command_check]).decode("utf-8").strip().split()
match = sum([[l[0] for l in w_list if p in l] for p in proc], [])
if len(match) > 0:
windowId = match[0]
if windowId != lastWindowId:
if skip > 0:
skip -= 1
print("skipped window: " + windowId)
lastWindowId = windowId
else:
print("new window detected: " + windowId)
if onlyHide:
subprocess.Popen(["xdotool", "windowunmap", windowId])
print("window was hidden: " + windowId)
else:
subprocess.Popen(["xdotool", "key", windowId, "alt+F4"])
print("window was closed: " + windowId)
actionsPerformed += 1
lastWindowId = windowId
if actionsPerformed == repeatAmmount:
break
except (IndexError, subprocess.CalledProcessError):
break
time.sleep(speed)
print("finished")
ฉันมาพร้อมกับวิธีแก้ปัญหาที่ค่อนข้างหรูหราซึ่งอาศัย แต่เพียงผู้เดียวxdotool
และมีประโยชน์มากสำหรับแอปพลิเคชันที่ไม่มีการโต้แย้ง"เริ่มย่อเล็กสุด"เช่น Telegram
เพียงข้อเสียคือการแก้ปัญหาที่จะต้องมีการสร้างขึ้นมาด้วยตนเองสำหรับแอปแต่ละ แต่สมมติว่าไม่ใช่ปัญหา(เช่นถ้าคุณต้องการที่จะ autostart โปรแกรมบางโดยไม่ต้องปล่อยให้มันก่อให้เกิดมลพิษหน้าจอของคุณหลังจากที่เข้าสู่ระบบใน)นี้เป็นง่ายมากและตรงไปตรงมา .
## Starts Telegram and immediately closes it
xdotool search --sync --onlyvisible --name '^Telegram$' windowclose &
telegram-desktop &
## Starts WhatsApp and immediately closes it
xdotool search --sync --onlyvisible --name '(\([0-9]*\) ){0,1}(WhatsApp$|WhatsApp Web$)' windowclose &
whatsapp-nativefier &
ในภาพรวมครั้งแรกคุณอาจคิดว่าเป็นการดีกว่าที่จะใช้กระบวนการ 'PID หรือคลาสเพื่อต่อต้าน ตัวอย่างคือหน้าต่าง 0x0 ที่รอการแจ้งเตือนไอคอน systray หรือหน้าต่าง "ซ่อน" อื่น ๆ
วิธีแก้ปัญหาคือการสร้างคำสั่ง xdotool ที่จะส่งคืนหน้าต่างที่ไม่ซ้ำกันเพียงหน้าต่างเดียวเสมอ ในทั้งสองตัวอย่างของฉันที่ได้กระทำโดยใช้--name
แต่คุณสามารถรวมตัวเลือกหลายที่มี--all
(เช่นตรงกับชื่อคลาส + ชื่อชั้นที่กำหนด + ชื่อ regex) โดยปกติ--name
regex ที่ดีจะหลอกลวงได้
หลังจากงานหัตถกรรมของคุณsearch
เงื่อนไขวางไข่เพียงตัวอย่างของ xdotool (ถอดออกจากเปลือก)กับพารามิเตอร์และเงื่อนไขของคุณตามด้วย--sync
windowclose
เรียกใช้แอปของคุณในภายหลัง:
xdotool search --sync [... myapp-match-conditions] windowclose &
my-app
ตรวจสอบ
xdotool search --help
ความเป็นไปได้ทั้งหมดของชุดค่าผสมที่คุณสามารถจัดเรียงเพื่อให้สามารถกำหนดเป้าหมายหน้าต่างแน่นอนที่คุณต้องการ บางครั้งมันจะยุ่งยากและคุณต้องรวมหลายเงื่อนไข แต่เมื่อคุณทำเสร็จแล้วมันจะไม่ค่อยเกิดความล้มเหลว (เว้นแต่การอัปเดตจะเปลี่ยนแอปพลิเคชันและทำให้การติดตั้งใช้งานไม่ได้)