Ich möchte nur, dass Telegramm ausgeführt wird, und ich habe es zu Start-Apps hinzugefügt. Der Punkt ist, dass ich es minimieren muss. Irgendwelche Befehle?
Ich möchte nur, dass Telegramm ausgeführt wird, und ich habe es zu Start-Apps hinzugefügt. Der Punkt ist, dass ich es minimieren muss. Irgendwelche Befehle?
Antworten:
Das minimierte Starten einer Anwendung erfordert zwei Befehle:
Daher muss der Befehl oder das Skript "intelligent" sein. Der zweite Befehl sollte warten, bis das Anwendungsfenster tatsächlich angezeigt wird.
Das folgende Skript erledigt dies und kann als allgemeine Lösung zum minimierten Starten einer Anwendung verwendet werden. Führen Sie es einfach in der folgenden Syntax aus:
<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
Das Skript benötigt beides wmctrl
und xdotool
:
sudo apt-get install wmctrl xdotool
Dann:
startup_minimizd.py
Testen Sie das Skript mit (zB) gedit
dem Befehl:
python3 /path/to/startup_minimizd.py gedit gedit
Startup Applications
wmctrl
) auf Fenster, die nach Ihrem zweiten Argument benannt sind.xdotool
Um eine Endlosschleife zu verhindern, wenn das Fenster aus irgendeinem Grund nicht angezeigt wird , verwendet das Skript ein Zeitlimit von 30 Sekunden, damit das Fenster angezeigt wird.Sie müssen nicht erwähnen, dass Sie das Skript für mehrere Anwendungen gleichzeitig verwenden können, da Sie es mit Argumenten außerhalb des Skripts ausführen.
Wenn der Fenstertitel unsicher oder variabel ist oder die Gefahr von Namenskonflikten im Namen des Fensters besteht, ist die Verwendung von pid
eine zuverlässigere Methode.
Das folgende Skript basiert auf der Verwendung der pid der Anwendung, wie in der Ausgabe von sowohl wmctrl -lp
als auch ps -ef
.
Das Setup ist ziemlich gleich, aber der Fenstertitel wird in dieser Version nicht benötigt, daher lautet der Befehl zum Ausführen:
python3 /path/to/startup_minimizd.py <command_to_run_application>
Genau wie das erste Skript braucht es beides wmctrl
undxdotool
#!/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)
Obwohl die zweite Version im Allgemeinen zuverlässiger sein sollte, unterscheidet sich die PID des Befehls in Fällen, in denen die Anwendung durch ein Wrapper-Skript gestartet wird, von der zuletzt aufgerufenen Anwendung.
In solchen Fällen empfehle ich die Verwendung des ersten Skripts.
Wie in einem Kommentar unten angefordert, wurde eine Version, die speziell für den Start von STEAM entwickelt wurde, minimiert.
Es stellt sich heraus, dass es Steam
sich ganz anders verhält als eine "normale" Anwendung:
Steam
läuft nicht eine PID, aber nicht weniger als (in meinem Test) acht!Steam
Läuft beim Start mit mindestens zwei Fenstern (einem spritzwasserähnlichen Fenster), manchmal wird jedoch ein zusätzliches Meldungsfenster angezeigt.pid 0
, das ist ein Problem im Skript wie es war.Dieses außergewöhnliche Verhalten Steam
erfordert eine spezielle Version des Skripts, die unten hinzugefügt wird. Das Skript wird gestartet Steam
und überwacht 12 Sekunden lang alle neuen Fenster des entsprechenden Fensters WM_CLASS
und prüft, ob sie minimiert sind. Wenn nicht, stellt das Skript sicher, dass dies der Fall ist.
Wie das Original - Skript, diese Bedürfnisse wmctrl
und xdotool
installiert werden.
#!/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
Führen Sie es mit dem Befehl:
python3 /path/to/runsteam_minimized.py
except:
nur um zurückzukehren. Lass es wahrscheinlich besser scheitern, damit du siehst, was gescheitert ist. Andernfalls kann es aus verschiedenen Gründen brechen und wird unbeworben weitergegeben.
subprocess.CalledProcesError
(als Ergebnis eines Buggys wmctrl
) und IndexError
(normale Ausnahme) werden in einer Minute bearbeitet :). Vielen Dank für die Erwähnung
Es ist gut, die Skripte von user72216 und Sergey als allgemeine Lösungen für das Problem zu haben, aber manchmal hat die Anwendung, die Sie minimieren möchten, bereits einen Schalter, der tut, was Sie wollen.
Hier einige Beispiele mit den entsprechenden Befehlszeichenfolgen für das Startprogramm:
-startintray
Option:<path-to-Telegram>/Telegram -startintray
-silent
Option:/usr/bin/steam %U -silent
--minimized
Option:/usr/bin/transmission-gtk --minimized
In Unity werden diese Anwendungen als Symbole in der oberen Menüleiste und nicht als Symbole im Startbildschirm minimiert. Das normale Startsymbol wird jedoch weiterhin angezeigt, sobald Sie die Anwendung starten. Andere Anwendungen verhalten sich möglicherweise anders.
Ich nahm Jacobs Skripte und änderte sie ein wenig, um sie universeller zu gestalten.
#!/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)
Hauptunterschiede sind:
WAIT_TIME sollte groß genug sein, damit das Programm seine untergeordneten Prozesse verzweigen kann. Auf meinem Computer reicht es für große Programme wie Steam. Erhöhen Sie es bei Bedarf.
Zusatz
xdotool
Die Option von windowunmap
kann mit einigen Anwendungen und Tray-Programmen (z. B. Linux Mint's Tray) funky funktionieren. Hier ist eine alternative Version des Skripts für diese Ausnahmen.
#!/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
. Dann rannte ich startminimized gnome-calendar
. Kalender geöffnet und weiterlaufen?
WAIT_TIME
. Ich benutze eine Verzögerung von 40 Sekunden für schwache Computer. Sie können auch ein zweites Skript ausprobieren, da es einen anderen Befehl verwendet, um die App zu minimieren.
Wenn das Programm in die Taskleiste geschlossen wird, möchten Sie möglicherweise das Programmfenster beim Start schließen, anstatt es zu minimieren. Ein Beispiel für ein solches Programm ist Viber. In diesem Fall könnte man folgendes Skript verwenden 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
Verwendung: <path-to-script> <program-to-start>
xdotool
wissen , dass dies bei Installationen mit Wayland nicht ordnungsgemäß funktioniert.
Ich habe gerade gesurft und bin auf diese Frage gestoßen, also habe ich mich nur gefragt, was Ihr Betriebssystem ist. Ich verwende UBUNTU BUDGIE 18.04 LTS, daher ist es in diesem Betriebssystem sehr einfach.
Gehen Sie einfach zum Menü
Gehen Sie im Menü zu den Budgie Desktop-Einstellungen
und
Gehen Sie in den Desktop-Einstellungen zu Auto Start
Es gibt Ihnen 2 Optionen, von "+" hinzufügen
1. Anwendung hinzufügen
2. Befehl hinzufügen
Wenn Sie Add Application ( Anwendung hinzufügen) auswählen, werden alle Anwendungen aufgelistet. Wählen Sie eine beliebige Anwendung aus. Sie wird beim Starten des Computers gestartet und minimiert.
Ich brauchte die Programme in der Taskleiste geschlossen, nicht minimiert, und ich habe alle hier veröffentlichten Skripte ausprobiert, die funktionierten, nur für einige Programme und nicht für andere. Daher habe ich ein Programm programmiert, das viel besser funktioniert (das Fenster wird fast nicht angezeigt, nur das Taskleistensymbol, es sieht nativ aus) und das für alle Programme funktioniert, die ich ausprobiert habe. Es basiert auf dem von Jacob. Mit diesem Skript müssen Sie möglicherweise je nach Programm ein Argument hinzufügen (siehe unten), aber bei mir hat es immer mit vielen Programmen funktioniert. Es sollte auch mit Steam funktionieren.
Verwendung:
sudo apt-get install wmctrl xdotool
startup_closed.py
Sie ihm Ausführungsberechtigungen erteilen, und führen Sie es dann auspython3 ./startup_closed.py -c <command to open program>
-splash
oder -hide
, durch Ausprobieren. Zum Beispiel: python3 ./startup_closed.py -hide -c teamviewer
oderpython3 ./startup_closed.py -splash -c slack
./startup_closed.py --help
Skript:
#!/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")
Ich kam mit einer ziemlich eleganten Lösung, die sich ausschließlich auf xdotool
sie stützt , und sie ist sehr nützlich für Anwendungen, die kein "start minimized" -Argument haben, wie z. B. Telegram.
Der einzige Nachteil ist, dass die Lösung für jede App manuell erstellt werden muss. Vorausgesetzt, dies ist kein Problem (z. B. wenn Sie eine bestimmte Anwendung automatisch starten möchten, ohne zuzulassen, dass der Bildschirm nach dem Anmelden verschmutzt wird) , ist dies viel einfacher und unkomplizierter .
## 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 &
Auf den ersten Blick könnten Sie denken, dass es besser ist, die PID oder Klasse des Prozesses zu verwenden, um eine Übereinstimmung zu erzielen. Dies ist jedoch tatsächlich kontraproduktiv, da Sie häufig mehrere Ergebnisse für dieselbe PID erhalten. Beispiele sind ein 0x0-Fenster, das tatsächlich auf eine Benachrichtigung wartet, ein Systray-Symbol oder ein anderes "verstecktes" Fenster.
Die Lösung besteht darin , einen xdotool-Befehl zu erstellen, der immer nur ein einziges Fenster zurückgibt . In meinen beiden Beispielen, die mit ausgeführt wurden --name
, können Sie jedoch mehrere Selektoren mit kombinieren --all
(z. B. Übereinstimmung mit einem bestimmten Klassennamen + einem Klassennamen + einem regulären Namen) . Normalerweise reicht ein guter --name
Regex aus.
Nachdem Sie Ihre search
Bedingungen erstellt haben, erzeugen Sie einfach eine Instanz von xdotool (von der Shell getrennt) mit dem --sync
Parameter und Ihren Bedingungen, gefolgt von windowclose
. Führen Sie Ihre App anschließend aus:
xdotool search --sync [... myapp-match-conditions] windowclose &
my-app
Informieren Sie sich
xdotool search --help
über alle Kombinationsmöglichkeiten, die Sie einrichten können, um genau das gewünschte Fenster zu finden. Manchmal wird es schwierig und Sie müssen mehrere Bedingungen kombinieren, aber wenn Sie fertig sind, wird es selten fehlschlagen (es sei denn, ein Update ändert die Anwendung und bringt Ihre Implementierung zum Erliegen).