Tôi chỉ muốn Telegram được chạy và tôi đã thêm nó vào các ứng dụng khởi động. Vấn đề là tôi cần nó để được giảm thiểu. Bất kỳ lệnh nào?
Tôi chỉ muốn Telegram được chạy và tôi đã thêm nó vào các ứng dụng khởi động. Vấn đề là tôi cần nó để được giảm thiểu. Bất kỳ lệnh nào?
Câu trả lời:
Khởi động một ứng dụng theo cách tối thiểu hóa cần hai lệnh:
Do đó, lệnh hoặc tập lệnh cần phải "thông minh"; lệnh thứ hai sẽ đợi cửa sổ ứng dụng thực sự xuất hiện.
Kịch bản dưới đây thực hiện điều đó và có thể được sử dụng như một giải pháp chung để khởi động ứng dụng theo cách tối thiểu hóa. Chỉ cần chạy nó theo cú pháp:
<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
Kịch bản cần cả hai wmctrl
và xdotool
:
sudo apt-get install wmctrl xdotool
Sau đó:
startup_minimizd.py
Kiểm tra- chạy tập lệnh với (ví dụ) gedit
lệnh:
python3 /path/to/startup_minimizd.py gedit gedit
Startup Applications
wmctrl
) cho các cửa sổ, được đặt tên theo đối số thứ hai của bạn.xdotool
Để ngăn chặn vòng lặp vô tận nếu cửa sổ có thể không xuất hiện vì một số lý do, tập lệnh thực hiện giới hạn thời gian là 30 giây để cửa sổ xuất hiện.Không cần đề cập rằng bạn có thể sử dụng tập lệnh cho nhiều ứng dụng cùng một lúc, vì bạn chạy nó với các đối số bên ngoài tập lệnh.
Nếu tiêu đề cửa sổ không chắc chắn hoặc thay đổi hoặc có nguy cơ xung đột tên trong tên của cửa sổ, sử dụng pid
phương pháp đáng tin cậy hơn để sử dụng.
Kịch bản dưới đây dựa trên việc sử dụng pid của ứng dụng, như trong đầu ra của cả hai wmctrl -lp
và ps -ef
.
Thiết lập khá giống nhau, nhưng tiêu đề cửa sổ không cần thiết trong phiên bản này, vì vậy lệnh để chạy nó là:
python3 /path/to/startup_minimizd.py <command_to_run_application>
Giống như kịch bản đầu tiên, nó cần cả hai wmctrl
và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)
Mặc dù nói chung, phiên bản thứ hai sẽ đáng tin cậy hơn, nhưng trong trường hợp khi ứng dụng được khởi động bởi tập lệnh bao bọc, pid của lệnh sẽ khác với ứng dụng cuối cùng được gọi.
Trong những trường hợp như vậy, tôi khuyên bạn nên sử dụng tập lệnh đầu tiên.
Theo yêu cầu trong một bình luận, bên dưới một phiên bản, được tạo riêng để khởi động STEAM được giảm thiểu.
Hóa ra Steam
ứng xử này khá khác so với ứng dụng "thông thường":
Steam
không chạy một pid, nhưng không ít hơn (trong thử nghiệm của tôi) tám!Steam
chạy khi khởi động với ít nhất hai cửa sổ (một cửa sổ giống như giật gân), nhưng đôi khi một cửa sổ thông báo bổ sung xuất hiện.pid 0
một vấn đề trong kịch bản.Hành vi đặc biệt này Steam
yêu cầu một phiên bản đặc biệt của kịch bản, được thêm vào dưới đây. Kịch bản khởi động Steam
và trong 12 giây, nó theo dõi tất cả các cửa sổ mới tương ứng WM_CLASS
, kiểm tra xem chúng có được thu nhỏ không. Nếu không, kịch bản đảm bảo họ sẽ được.
Giống như kịch bản gốc, cái này cần wmctrl
và xdotool
được cài đặt.
#!/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
Chạy nó bằng lệnh:
python3 /path/to/runsteam_minimized.py
except:
chỉ để trở về Không. Có lẽ tốt hơn là để nó thất bại để bạn thấy những gì thất bại; mặt khác, nó có thể phá vỡ cho bất kỳ loại nguyên nhân khác nhau và sẽ vượt qua không được báo cáo.
subprocess.CalledProcesError
(là kết quả của một lỗi wmctrl
) và IndexError
(ngoại lệ bình thường) sẽ chỉnh sửa trong một phút :). Cảm ơn đã đề cập
Thật tốt khi có các tập lệnh được đưa ra bởi user72216 và Sergey làm giải pháp chung cho vấn đề, nhưng đôi khi ứng dụng bạn muốn khởi động được thu nhỏ đã có một công tắc sẽ làm những gì bạn muốn.
Dưới đây là một vài ví dụ với chuỗi lệnh chương trình khởi động tương ứng:
-startintray
tùy chọn:<path-to-Telegram>/Telegram -startintray
-silent
tùy chọn:/usr/bin/steam %U -silent
--minimized
tùy chọn:/usr/bin/transmission-gtk --minimized
Trong Unity, các ứng dụng này bắt đầu được thu nhỏ dưới dạng biểu tượng trong thanh menu trên cùng thay vì biểu tượng trên trình khởi chạy, mặc dù biểu tượng khởi chạy bình thường sẽ vẫn xuất hiện khi bạn bắt đầu sử dụng ứng dụng. Các ứng dụng khác có thể hành xử khác nhau.
Tôi lấy kịch bản của Jacob và sửa đổi chúng một chút để tạo ra một kịch bản phổ quát hơn.
#!/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)
Sự khác biệt chính là:
WAIT_TIME phải được đặt đủ lớn để cho phép chương trình rẽ nhánh các tiến trình con của nó. Trên máy tính của tôi, nó là đủ cho các chương trình lớn như hơi nước. Tăng nó, nếu cần.
Thêm vào
xdotool
Tùy chọn của windowunmap
có thể hoạt động sôi nổi với một số ứng dụng và chương trình khay (ví dụ: khay của mint linux), vì vậy đây là phiên bản thay thế của tập lệnh cho những trường hợp ngoại lệ đó.
#!/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
. Rồi tôi chạy startminimized gnome-calendar
. Lịch mở và tiếp tục chạy?
WAIT_TIME
. Tôi sử dụng độ trễ 40 giây cho các máy tính yếu. Ngoài ra, bạn có thể thử tập lệnh thứ hai vì nó sử dụng một lệnh khác để thu nhỏ ứng dụng.
Nếu chương trình đang được đóng vào khay, người ta thực sự có thể muốn đóng cửa sổ chương trình khi khởi động thay vì thu nhỏ nó. Một ví dụ về chương trình như vậy là Viber. Trong trường hợp này, người ta có thể sử dụng tập lệnh sau 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
Sử dụng: <path-to-script> <program-to-start>
xdotool
sẽ không hoạt động đúng khi cài đặt với Wayland.
Tôi vừa lướt web và bắt gặp câu hỏi này, vì vậy tôi chỉ tự hỏi hệ điều hành của bạn là gì? Đối với tôi, tôi đang sử dụng UBUNTU BUDGIE 18.04 LTS, vì vậy trong hệ điều hành này, nó rất đơn giản.
Đơn giản chỉ cần đi đến menu
Từ Menu đi đến Cài đặt máy tính để bàn Budgie
và
Từ Cài đặt máy tính để bàn đến Tự động bắt đầu
Nó sẽ cung cấp cho bạn 2 tùy chọn, từ "+" thêm
1. Thêm ứng dụng
2. Thêm lệnh
Bằng cách chọn Thêm ứng dụng, tất cả các ứng dụng sẽ được liệt kê, chọn bất kỳ ứng dụng nào bạn muốn và ứng dụng sẽ khởi động khi bạn khởi động máy tính và nó cũng sẽ được thu nhỏ.
Tôi cần các chương trình được đóng vào khay, không được thu nhỏ và tôi đã thử tất cả các tập lệnh được đăng ở đây, những tập lệnh đã hoạt động, chỉ hoạt động cho một số chương trình chứ không phải cho các chương trình khác. Vì vậy, tôi đã mã hóa một cái hoạt động tốt hơn nhiều (bạn hầu như không thấy cửa sổ xuất hiện, chỉ có biểu tượng khay, trông giống bản địa) và hoạt động cho tất cả các chương trình tôi đã thử. Nó dựa trên cơ sở của Jacob. Với kịch bản này, bạn có thể cần thêm một đối số tùy thuộc vào chương trình (xem bên dưới) nhưng luôn hoạt động với tôi với rất nhiều chương trình, nó cũng sẽ hoạt động với steam.
Sử dụng:
sudo apt-get install wmctrl xdotool
startup_closed.py
cấp cho nó quyền thực thi và sau đó thực thipython3 ./startup_closed.py -c <command to open program>
-splash
hoặc -hide
, bằng cách dùng thử và lỗi. Ví dụ: python3 ./startup_closed.py -hide -c teamviewer
hoặcpython3 ./startup_closed.py -splash -c slack
./startup_closed.py --help
Kịch bản:
#!/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")
Tôi đã đưa ra một giải pháp khá thanh lịch chỉ dựa vào xdotool
và nó khá hữu ích cho các ứng dụng không có đối số "bắt đầu thu nhỏ" , như Telegram.
Nhược điểm duy nhất là giải pháp đó phải được tạo thủ công cho từng ứng dụng, nhưng giả sử đó không phải là vấn đề (ví dụ: nếu bạn muốn tự động khởi động một ứng dụng nào đó mà không cho phép nó làm ô nhiễm màn hình của bạn sau khi đăng nhập) , việc này đơn giản và đơn giản hơn nhiều .
## 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 &
Thoạt nhìn, bạn có thể nghĩ rằng tốt hơn là sử dụng quy trình 'PID hoặc lớp để đối chiếu, tuy nhiên điều đó thực sự phản tác dụng vì bạn thường sẽ nhận được nhiều kết quả cho cùng một PID. Ví dụ là một cửa sổ 0x0 thực sự đang chờ thông báo, biểu tượng systray hoặc bất kỳ cửa sổ "ẩn" nào khác.
Giải pháp là tạo một lệnh xdotool luôn chỉ trả về một cửa sổ duy nhất . Trong cả hai ví dụ của tôi đã được thực hiện bằng cách sử dụng --name
, tuy nhiên, bạn có thể kết hợp nhiều bộ chọn với --all
(ví dụ: khớp với tên lớp đã cho + tên lớp + tên regex) . Thông thường một --name
regex tốt thực hiện các mẹo.
Sau khi tạo các search
điều kiện của bạn , chỉ cần tạo ra một thể hiện của xdotool (tách ra khỏi vỏ) với --sync
tham số và các điều kiện của bạn, theo sau là windowclose
. Chạy ứng dụng của bạn sau đó:
xdotool search --sync [... myapp-match-conditions] windowclose &
my-app
Kiểm tra
xdotool search --help
tất cả các khả năng kết hợp bạn có thể sắp xếp để có thể nhắm mục tiêu chính xác cửa sổ bạn muốn. Đôi khi nó trở nên khó khăn và bạn phải kết hợp một số điều kiện, nhưng một khi bạn đã hoàn thành, nó sẽ hiếm khi thất bại (trừ khi bản cập nhật thay đổi ứng dụng và phá vỡ việc triển khai của bạn, tất nhiên).