Voglio solo far funzionare Telegram e l'ho aggiunto alle app di avvio. Il punto è che ne ho bisogno per essere minimizzato. Qualche comando?
Voglio solo far funzionare Telegram e l'ho aggiunto alle app di avvio. Il punto è che ne ho bisogno per essere minimizzato. Qualche comando?
Risposte:
L'avvio di un'applicazione in modo ridotto richiede due comandi:
Pertanto, il comando o lo script deve essere "intelligente"; il secondo comando dovrebbe attendere che appaia effettivamente la finestra dell'applicazione.
Lo script seguente lo fa e può essere utilizzato come soluzione generale per avviare un'applicazione in modo ridotto. Basta eseguirlo nella sintassi:
<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
Lo script ha bisogno di entrambi wmctrl
e xdotool
:
sudo apt-get install wmctrl xdotool
Poi:
startup_minimizd.py
Prova- esegui lo script con (es.) gedit
Il comando:
python3 /path/to/startup_minimizd.py gedit gedit
Startup Applications
wmctrl
) per windows, che prende il nome dal tuo secondo argomento.xdotool
Per evitare un ciclo infinito se la finestra potrebbe non apparire per qualche motivo, lo script applica un limite di tempo di 30 secondi per la visualizzazione della finestra.Non è necessario menzionare che è possibile utilizzare lo script per più applicazioni contemporaneamente, poiché lo si esegue con argomenti esterni allo script.
Se il titolo della finestra non è sicuro o variabile, oppure esiste il rischio di scontro di nomi nel nome della finestra, è possibile utilizzare il pid
metodo più affidabile.
Lo script seguente si basa sull'uso del pid dell'applicazione, come nell'output di entrambi wmctrl -lp
e ps -ef
.
L'installazione è praticamente la stessa, ma il titolo della finestra non è necessario in questa versione, quindi il comando per eseguirlo è:
python3 /path/to/startup_minimizd.py <command_to_run_application>
Proprio come il primo copione, ha bisogno di entrambi wmctrl
exdotool
#!/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)
Sebbene in generale la seconda versione dovrebbe essere più affidabile, nei casi in cui l'applicazione viene avviata da uno script wrapper, il pid del comando sarà diverso dall'applicazione che viene finalmente chiamata.
In questi casi, ti consiglio di usare il primo script.
Come richiesto in un commento, sotto una versione, realizzata appositamente per l'avvio di STEAM minimizzata.
Si scopre che Steam
si comporta in modo abbastanza diverso da un'applicazione "normale":
Steam
che non esegue un pid, ma non meno di (nel mio test) otto!Steam
viene eseguito all'avvio con almeno due finestre (una finestra simile a uno splash), ma a volte viene visualizzata una finestra di messaggio aggiuntiva.pid 0
, che è un problema nello script così com'era.Questo comportamento eccezionale Steam
richiede una versione speciale dello script, che viene aggiunta di seguito. Lo script si avvia Steam
e, per 12 secondi, tiene d'occhio tutte le nuove finestre del corrispondente WM_CLASS
, controllando se sono minimizzate. In caso contrario, lo script si assicura che lo saranno.
Come lo script originale, questo si ha bisogno wmctrl
e xdotool
da installare.
#!/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
Eseguilo con il comando:
python3 /path/to/runsteam_minimized.py
except:
solo per restituire None. Probabilmente è meglio lasciarlo fallire in modo da vedere cosa è fallito; in caso contrario, può rompersi per qualsiasi tipo di cause diverse e passerà senza pubblicità.
subprocess.CalledProcesError
(a seguito di un bug wmctrl
) e IndexError
(normale eccezione) verranno modificate in un minuto :). Grazie per la menzione
È bene avere gli script forniti da user72216 e Sergey come soluzioni generali al problema, ma a volte l'applicazione che si desidera avviare al minimo ha già un interruttore che farà ciò che si desidera.
Ecco alcuni esempi con le stringhe di comando del programma di avvio corrispondenti:
-startintray
opzione:<path-to-Telegram>/Telegram -startintray
-silent
opzione:/usr/bin/steam %U -silent
--minimized
opzione:/usr/bin/transmission-gtk --minimized
In Unity queste applicazioni iniziano a essere minimizzate come icone nella barra dei menu in alto anziché come icone nel programma di avvio, anche se l'icona di avvio normale verrà comunque visualizzata una volta che inizi a utilizzare l'applicazione. Altre applicazioni potrebbero comportarsi diversamente.
Ho preso gli script di Jacob e li ho modificati un po 'per renderli più universali.
#!/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)
Le principali differenze sono:
WAIT_TIME dovrebbe essere impostato abbastanza grande da consentire al programma di fork i suoi processi figlio. Sul mio computer è sufficiente per grandi programmi come Steam. Aumentalo, se necessario.
aggiunta
xdotool
L 'opzione windowunmap
potrebbe funzionare in modo strano con alcune applicazioni e programmi di notifica (ad esempio il vassoio di Linux Mint), quindi ecco una versione alternativa dello script per quelle eccezioni.
#!/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
. Poi ho corso startminimized gnome-calendar
. Calendario aperto e continua a funzionare?
WAIT_TIME
. Uso un ritardo di 40 secondi per i computer deboli. Inoltre, puoi provare il secondo script in quanto utilizza un comando diverso per ridurre a icona l'app.
Se il programma viene chiuso nel vassoio, si potrebbe effettivamente voler chiudere la finestra del programma all'avvio invece di minimizzarlo. Un esempio di tale programma è Viber. In questo caso si potrebbe usare il seguente script 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
Uso: <path-to-script> <program-to-start>
xdotool
non funzionerà correttamente su installazioni con Wayland.
Stavo solo navigando e mi sono imbattuto in questa domanda, quindi mi chiedevo quale fosse il tuo sistema operativo? Per quanto mi riguarda sto usando UBUNTU BUDGIE 18.04 LTS, quindi in questo sistema operativo è molto semplice.
Vai semplicemente al menu
Dal menu vai a Impostazioni desktop Budgie
e
Da Impostazioni desktop vai a Avvio automatico
Ti darà 2 opzioni, da "+" aggiungi
1. Aggiungi applicazione
2. Aggiungi comando
Selezionando Aggiungi applicazione verranno elencate tutte le applicazioni selezionate qualsiasi applicazione desiderata e verrà avviata all'avvio del computer e verrà anche ridotta a icona.
Avevo bisogno dei programmi chiusi nel vassoio, non minimizzati, e ho provato tutti gli script pubblicati qui, quelli che funzionavano, funzionavano solo per alcuni programmi e non per altri. Quindi ho codificato uno che funziona molto meglio (quasi non vedi apparire la finestra, solo l'icona nella barra delle applicazioni, sembra nativa) e funziona per tutti i programmi che ho provato. Si basa su quello di Jacob. Con questo script potresti dover aggiungere un argomento a seconda del programma (vedi sotto) ma ha sempre funzionato per me con molti programmi e dovrebbe funzionare anche con Steam.
Uso:
sudo apt-get install wmctrl xdotool
startup_closed.py
concedergli le autorizzazioni di esecuzione ed eseguirlopython3 ./startup_closed.py -c <command to open program>
-splash
oppure -hide
, per tentativi ed errori. Ad esempio: python3 ./startup_closed.py -hide -c teamviewer
opython3 ./startup_closed.py -splash -c slack
./startup_closed.py --help
script:
#!/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")
Sono arrivato con una soluzione piuttosto elegante che si basa esclusivamente su xdotool
, ed è abbastanza utile per le applicazioni che non hanno un argomento "start minimized" , come Telegram.
L'unico aspetto negativo è che la soluzione deve essere elaborata manualmente per ogni app, ma supponendo che non sia un problema (ad esempio: se si desidera avviare automaticamente una determinata applicazione senza consentirle di inquinare lo schermo dopo aver effettuato l'accesso) , questo è molto più semplice e diretto .
## 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 &
A prima vista, potresti pensare che sia meglio usare il processo 'PID o classe per confrontarsi, tuttavia è effettivamente controproducente poiché spesso otterrai più risultati per lo stesso PID. Esempi sono una finestra 0x0 che sta effettivamente aspettando una notifica, un'icona systray o qualsiasi altra finestra "nascosta".
La soluzione sta creando un comando xdotool che restituisce sempre solo una finestra unica . In entrambi i miei esempi che sono stati fatti usando --name
, tuttavia è possibile combinare più selettori con --all
(ad esempio: abbina un dato nome classe + un nome classe + un nome regex) . Di solito un buon --name
regex fa il trucco.
Dopo aver creato le tue search
condizioni, genera semplicemente un'istanza di xdotool (staccato dalla shell) con il --sync
parametro e le tue condizioni, seguito da windowclose
. Esegui la tua app in seguito:
xdotool search --sync [... myapp-match-conditions] windowclose &
my-app
Scopri
xdotool search --help
tutte le possibilità di combinazioni che puoi organizzare per poter scegliere come target la finestra esatta che desideri. A volte diventa complicato e devi combinare diverse condizioni, ma una volta terminato, raramente fallirà mai (a meno che un aggiornamento non cambi l'applicazione e interrompa l'implementazione, ovviamente).