Solo quiero que se ejecute Telegram y lo he agregado a las aplicaciones de inicio. El punto es que necesito que se minimice. Cualquier comando?
Solo quiero que se ejecute Telegram y lo he agregado a las aplicaciones de inicio. El punto es que necesito que se minimice. Cualquier comando?
Respuestas:
Iniciar una aplicación de forma minimizada requiere dos comandos:
Por lo tanto, el comando o script debe ser "inteligente"; el segundo comando debería esperar a que aparezca la ventana de la aplicación.
El siguiente script hace eso y puede usarse como una solución general para iniciar una aplicación de manera minimizada. Simplemente ejecútelo en la sintaxis:
<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
El script necesita ambos wmctrl
y xdotool
:
sudo apt-get install wmctrl xdotool
Luego:
startup_minimizd.py
Prueba: ejecute el script con (por ejemplo) gedit
el comando:
python3 /path/to/startup_minimizd.py gedit gedit
Startup Applications
wmctrl
) para las ventanas, nombradas después de su segundo argumento.xdotool
Para evitar un bucle sin fin si la ventana puede no aparecer por alguna razón, el script practica un límite de tiempo de 30 segundos para que aparezca la ventana.No es necesario mencionar que puede usar el script para múltiples aplicaciones a la vez, ya que lo ejecuta con argumentos fuera del script.
Si el título de la ventana es inseguro o variable, o existe un riesgo de conflictos de nombres en el nombre de la ventana, utilizar pid
es un método más confiable de usar.
El siguiente script se basa en el uso del pid de la aplicación, como en la salida de ambos wmctrl -lp
y ps -ef
.
La configuración es prácticamente la misma, pero el título de la ventana no es necesario en esta versión, por lo que el comando para ejecutarlo es:
python3 /path/to/startup_minimizd.py <command_to_run_application>
Al igual que el primer guión, necesita ambos wmctrl
yxdotool
#!/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)
Aunque, en general, la segunda versión debería ser más confiable, en los casos en que la aplicación se inicia mediante un script de contenedor, el pid del comando será diferente de la aplicación que finalmente se llama.
En tales casos, recomiendo usar el primer script.
Como se solicitó en un comentario, debajo de una versión, hecha específicamente para iniciar STEAM minimizada.
Resulta que se Steam
comporta bastante diferente de una aplicación "normal":
Steam
que no ejecuta un pid, ¡pero no menos que (en mi prueba) ocho!Steam
se ejecuta al inicio con al menos dos ventanas (una ventana de tipo splash), pero a veces aparece una ventana de mensaje adicional.pid 0
, lo cual es un problema en el script tal como estaba.Este comportamiento excepcional de Steam
pide una versión especial del script, que se agrega a continuación. El script se inicia Steam
y, durante 12 segundos, vigila todas las ventanas nuevas de la correspondiente WM_CLASS
, verificando si están minimizadas. Si no, el script se asegura de que lo sean.
Al igual que el script original, este necesita wmctrl
y xdotool
debe instalarse.
#!/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
Ejecútelo con el comando:
python3 /path/to/runsteam_minimized.py
except:
solo para devolver Ninguno. Probablemente sea mejor dejar que falle para que veas lo que falló; de lo contrario, puede romperse por cualquier tipo de causas diferentes y pasará sin publicidad.
subprocess.CalledProcesError
(como resultado de un error wmctrl
) y IndexError
(excepción normal) se editará en un minuto :). Gracias por mencionar
Es bueno tener las secuencias de comandos proporcionadas por user72216 y Sergey como soluciones generales al problema, pero a veces la aplicación que desea iniciar minimizada ya tiene un interruptor que hará lo que desee.
Aquí hay algunos ejemplos con las cadenas de comando del programa de inicio correspondientes:
-startintray
opción:<path-to-Telegram>/Telegram -startintray
-silent
opción:/usr/bin/steam %U -silent
--minimized
opción:/usr/bin/transmission-gtk --minimized
En Unity, estas aplicaciones comienzan minimizadas como íconos en la barra de menú superior en lugar de como íconos en el iniciador, aunque el ícono de inicio normal aún aparecerá una vez que comience a usar la aplicación. Otras aplicaciones pueden comportarse de manera diferente.
Tomé los guiones de Jacob y los modifiqué un poco para que fueran más universales.
#!/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)
Las principales diferencias son:
WAIT_TIME debe establecerse lo suficientemente grande como para permitir que el programa bifurque sus procesos secundarios. En mi computadora es suficiente para grandes programas como steam. Aumentarlo, si es necesario.
Adición
xdotool
La opción windowunmap
puede funcionar con algunas aplicaciones y programas de bandeja (bandeja de Linux mint, por ejemplo), así que aquí hay una versión alternativa del script para esas excepciones.
#!/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
. Entonces corrí startminimized gnome-calendar
. Calendario abierto y seguir funcionando?
WAIT_TIME
. Uso 40 segundos de retraso para computadoras débiles. También puede probar el segundo script, ya que utiliza un comando diferente para minimizar la aplicación.
Si el programa se está cerrando en la bandeja, en realidad es posible que desee cerrar la ventana del programa al inicio en lugar de minimizarlo. Un ejemplo de dicho programa es Viber. En este caso, se podría usar el siguiente 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
no funcionará correctamente en instalaciones con Wayland.
Estaba navegando y me encontré con esta pregunta, así que me preguntaba cuál es su sistema operativo. En cuanto a mí, estoy usando UBUNTU BUDGIE 18.04 LTS, por lo que en este sistema operativo es muy simple.
Simplemente ve al menú
Desde el menú, vaya a Configuración de escritorio Budgie
y
Desde la configuración del escritorio, vaya a Inicio automático
Te dará 2 opciones, desde "+" agregar
1. Agregar aplicación
2. Agregar comando
Al seleccionar Agregar aplicación, se enumerarán todas las aplicaciones, seleccione la aplicación que desee y se iniciará cuando inicie su computadora y también se minimizará.
Necesitaba los programas cerrados a la bandeja, no minimizados, y he probado todos los scripts publicados aquí, los que funcionaron, funcionaron solo para algunos programas y no para otros. Así que he codificado uno que funciona mucho mejor (casi no ves aparecer la ventana, solo el icono de la bandeja, parece nativo) y funciona para todos los programas que he probado. Está basado en el de Jacob. Con este script, es posible que deba agregar un argumento según el programa (consulte a continuación), pero siempre funcionó para mí con muchos programas, también debería funcionar con steam.
Uso:
sudo apt-get install wmctrl xdotool
startup_closed.py
darle permisos de ejecución y luego ejecutepython3 ./startup_closed.py -c <command to open program>
-splash
o -hide
por prueba y error. Por ejemplo: python3 ./startup_closed.py -hide -c teamviewer
opython3 ./startup_closed.py -splash -c slack
./startup_closed.py --help
Guió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")
Llegué con una solución bastante elegante que se basa exclusivamente en xdotool
, y es bastante útil para aplicaciones que no tienen un argumento de "inicio minimizado" , como Telegram.
El único inconveniente es que la solución debe diseñarse manualmente para cada aplicación, pero suponiendo que no sea un problema (por ejemplo: si desea iniciar automáticamente una determinada aplicación sin permitir que contamine su pantalla después de iniciar sesión) , esto es mucho más simple y directo .
## 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 primera vista, puede pensar que es mejor usar el proceso 'PID o clase para comparar, sin embargo, eso es realmente contraproducente ya que con frecuencia obtendrá múltiples resultados para el mismo PID. Los ejemplos son una ventana 0x0 que realmente está esperando una notificación, un icono de bandeja del sistema o cualquier otra ventana "oculta".
La solución es crear un comando xdotool que siempre devuelva solo una ventana única . En mis dos ejemplos que se hicieron usando --name
, sin embargo, puede combinar múltiples selectores con --all
(por ejemplo: hacer coincidir un nombre de clase dado + un nombre de clase + una expresión regular de nombre) . Por lo general, una buena --name
expresión regular hace el truco.
Después de crear sus search
condiciones, simplemente genere una instancia de xdotool (separada del caparazón) con el --sync
parámetro y sus condiciones, seguido de windowclose
. Ejecute su aplicación después:
xdotool search --sync [... myapp-match-conditions] windowclose &
my-app
Consulte
xdotool search --help
todas las posibilidades de combinaciones que puede organizar para poder apuntar a la ventana exacta que desea. A veces se vuelve complicado y tiene que combinar varias condiciones, pero una vez que haya terminado, rara vez fallará (a menos que una actualización cambie la aplicación y rompa su implementación, por supuesto).