У меня есть три скрипта, которые я должен запустить, когда я запускаю свою машину Ubuntu, они запускают сервисы, которые я использую в своей среде разработки.
Чтобы сделать это, я вручную открываю три терминала и тип в командах.
Там какой-либо путь состоит в том, чтобы создать сценарий, который откроет три терминала и выполнит одну команду в каждом из них? (Каждая команда должна быть в отдельном окне терминала, таким образом, я вижу их вывод).
gnome-terminal -- command
или
xterm -e command
или
konsole -e command
Почти
terminal -e command
В konsole есть флаг --noclose
.
В xterm флаг - hold
.
В gnome-терминале
перейдите к Edit -> Profile Preferences -> Title. Перейдите на вкладку Command. Выберите Удерживайте клемму в раскрывающемся меню с надписью Когда команда выходит . Для этого нужно создать новый профиль и выполнить с помощью
gnome-terminal --window-with-profile=NAMEOFTHEPROFILE -e command
Вместо жесткого кодирования gnome-терминала
, konsole
, и т.д., используйте систему Alternatives. Программа, которая выполняет эмулятор терминала по умолчанию:
x-terminal-emulator
В моей системе она открывает новый экземпляр Konsole каждый раз, когда я выполняю эту команду.
К счастью, кажется, что терминалы поддерживают опцию -e
для выполнения команды (я проверил ее для konsole
и gnome-terminal
). Аргументы после команды передаются вызываемой команде. Бэш отказывается оставаться открытым в моем терминале, для получения терминала нужен дополнительный скрипт:
#!/bin/sh
"$@"
exec "$SHELL"
Если вы сохранили предыдущий скрипт как /home/user/hacky
и сделали его исполняемым, вы запустите свои скрипты с:
x-terminal-emulator -e /home/user/hacky your-script optional arguments here
Требуется полный путь и /home/user/hacky
должен быть исполняемым.
Моя предыдущая попытка запустить скрипт в новом терминальном окне может быть найдена в ревизии #2, это было до того, как я понял, что аргументы могут быть переданы в x-terminal-emulator
.
Проще говоря-
#!/bin/bash
/etc/init.d/ccpd status
Этого достаточно для другие команды, которым не нужно ничего отображать в терминале. Но здесь нужно видеть отображаемый статус.
Итак, он должен запускаться в окне терминала
#!/bin/bash
gnome-terminal -e "/etc/init.d/ccpd status" --window-with-profile=NAMEOFTHEPROFILE
Другой пост предназначался []
как заполнитель
Здесь «NAMEOFTHEPROFILE» следует заменить на имя профиля, который «Содержит терминал, когда команда завершается ".
Используйте экранную команду и -d отсоединиться от существующего сеанса экрана и снова подключить здесь -m инициировать новый сеанс экрана -S создайте именованный сеанс вместо использования имени по умолчанию
, комментируя ответ от Lekensteyn. Я знаю, что это старая заметка, но для всех, кто находит это полезным (как я только что сделал). Вместо того, чтобы делать очередной "хаки-скрипт", просто поместите функцию в вызываемый вами скрипт
hacky_function()
{
"$@"
exec "$SHELL"
}
Вызовите скрипт с "x-terminal-emulator -e /path/to/script hacky_function optional arguments here"
Не забудьте поставить "$@" в конце скрипта
С помощью ответа @ nickguletskii и моего собственного комментария под его ответом, а также вдохновленного голосом @ grabantot моего комментария, вот мой предпочтительный способ сделать это, особенно когда я хочу, чтобы терминал оставался открытым, чтобы Затем я могу использовать его вручную.
Исх. использование: это действительно полезно для добавления в ваши программы запуска, чтобы этот сценарий запускался, открывал терминал, создавал и называл вкладку в терминале и запускал команду за вас. Или вы можете просто добавить символическую ссылку на этот скрипт на свой рабочий стол. Я использую этот тип подхода, поэтому я могу дважды щелкнуть один значок на моем рабочем столе и открыть несколько терминалов (с различными вкладками, названными в зависимости от того, какую работу я собираюсь выполнять в них) и программ для настройки моя среда программирования, например, для повседневной работы.
Вот надуманный пример, который открывает одну вкладку, называет ее «тест», а затем запускает простую команду cd / etc; ls
внутри него. Часть $ SHELL
в конце заставляет оболочку оставаться открытой, чтобы вы могли увидеть ее вывод и продолжить его использование (я узнал об этом где-то еще в Stack Overflow):
gnome-terminal --tab --title="test" --command="bash -c 'cd /etc; ls; $SHELL'"
Вот более сложный пример, открывает 3 отдельные вкладки в одном и том же gnome-терминале. Это именно то, что делает мой ярлык на рабочем столе, поэтому я могу открыть сразу несколько окон программирования:
gnome-terminal --tab --title="tab 1" --command="bash -c 'cd /etc; ls; $SHELL'" --tab --title="tab 2" --command="bash -c 'cd ~; ls; $SHELL'" --tab --title="tab 3" --command="bash -c 'cd ~/temp3; ls; $SHELL'"
Вот разбивка этой команды выше:
gnome-terminal
= открыть gnome- терминал - tab
= открыть уникальную вкладку, чтобы узнать, что будет дальше - title = "tab 1"
= название этой вкладки "tab 1" - command = " bash -c 'cd / etc; ls; $ SHELL' "
= запустить bash -c 'cd / etc; ls; $ SHELL '
, которую я только что придумал в качестве примера; вот что он делает:
bash -c
говорит, что это команда bash 'c'ommand cd / etc
=' c'hange 'd'irectory в путь "/ etc" ls
= 'l'i's't содержимое этого каталога $ SHELL
= этот загадочный лакомый кусочек необходим для того, чтобы оболочка оставалась открытой, чтобы вы могли с ней работать. Если вы хотите, чтобы оболочка открылась, запустите вашу команду, затем закройте, просто удалите эту часть. Однако я хочу, чтобы вкладка оставалась открытой, чтобы я мог творить волшебство программирования. :) - tab
, чтобы создать вкладку 2, затем снова для вкладки 3. Настройте так, как вам нравится. Снимок экрана:
Почти десять лет спустя вечеринку, но вот мой ответ с использованием Python.
В приведенном ниже .gif
я запустил программу с существующего терминала с запущенным устройством записи экрана, чтобы показать, как это будет выглядеть при входе в систему:
Я написал программу на Python для этого ответа. Есть некоторые дополнительные функции, не запрашиваемые OP, но полезные для меня:
gnome-terminal
. gedit
и последние пять открытых файлов на отдельных вкладках. Программа python:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#==============================================================================
#
# dellstart - Autostart GUI applications on Dell Fileserver
#
#==============================================================================
'''
CALL:
dellstart
REQUIRES:
sudo apt install xdotool
'''
from __future__ import print_function # Must be first import
import os
import time
BASHRC_TIME = 2 # Seconds to load ~/.bashrc
WINDOW_TIME = .5 # Secpmds fpr window to appear
commands = [ 'gnome-terminal &', # Launch terminal in background
'sleep '+str(BASHRC_TIME), # Bash command wait a sec
'move x y', # Move windows to x and/or y
# 'move 2100 1000', # triple monitor setup
'xdotool type "cd ~"', # Change to home directory
'xdotool key Return', # Enter Key
'xdotool type "./ssh-activity"', # Suspend after 15 minutes
'xdotool key Return', # Enter Key
'title SSH\ Activity', # Window title (escape spaces)
'xdotool key Control_L+Shift_L+T', # Open new terminal tab
'sleep '+str(BASHRC_TIME), # Bash command wait a sec
'xdotool type "cd ~/askubuntu"', # Change to working directory
'xdotool key Return', # Enter Key
'title Ask\ Ubuntu', # Window title (escape spaces)
'gedit', # Last 5 files will open up
'move x y', # Move windows to x and/or y
# 'move 3849 2266', # triple monitor setup
]
""" NOTE: To discover window coordinates, arrange on desktop and type:
wmctrl -lG
"""
def process_commands(command_list):
for command in command_list:
if command.endswith('&'):
# Launch in background and get window ID opened
active_pid, active_win = launch_command(command)
if active_pid == 0:
print("ERROR launching", command, \
"Aborting 'dellstart' script")
exit()
elif command.startswith('move'):
move_window(command, active_win)
elif command.startswith('title'):
terminal_title(command)
elif command.startswith('gedit'):
gedit()
else:
run_and_wait(command)
def launch_command(ext_name):
''' Launch external command in background and return PID to parent.
Use for programs requiring more than .2 seconds to run.
'''
all_pids = get_pids(ext_name) # Snapshot current PID list
all_wins = get_wins(all_pids) # Snapshot of windows open
new_pids = all_pids
new_wins = all_wins
sleep_count = 0 # Counter to prevent infinite loops
os.popen(ext_name) # Run command in background
while new_pids == all_pids: # Loop until new PID is assigned
new_pids = get_pids(ext_name) # Snapshot current PID list
if sleep_count > 0: # Don't sleep first time through loop
time.sleep(.005) # sleep 5 milliseconds
sleep_count += 1
if sleep_count == 1000: # 10 second time-out
print('launch_ext_command() ERROR: max sleep count reached')
print('External command name:',ext_name)
return 0
pid_list = list(set(new_pids) - set(all_pids))
if not len(pid_list) == 1:
print('launch_command() ERROR: A new PID could not be found')
return 0, 0
time.sleep(WINDOW_TIME) # Give time for window to appear
new_wins = get_wins(all_pids) # Snapshot of windows open
win_list = list(set(new_wins) - set(all_wins))
if not len(win_list) == 1:
#print('launch_command() ERROR: New Window ID could not be found')
#suppress error message because we aren't using window ID at all
return int(pid_list[0]), 0
# Return PID of program we just launched in background
return int(pid_list[0]), int(win_list[0])
def run_and_wait(ext_name):
''' Launch external command and wait for it to end.
Use for programs requiring less than .2 seconds to run.
'''
result = os.popen(ext_name).read().strip()
#print('run_and_wait() command:', ext_name)
return result
def get_pids(ext_name):
''' Return list of PIDs for program name and arguments
Whitespace output is compressed to single space
'''
all_lines = []
# Just grep up to first space in command line. It was failing on !
prog_name = ext_name.split(' ',1)[0]
all_lines = os.popen("ps aux | grep -v grep | grep " + \
"'" + prog_name + "'").read().strip().splitlines
PID = []
for l in all_lines():
l = ' '.join(l.split()) # Compress whitespace into single space
PID.append(int(l.split(' ', 2)[1]))
return PID
def get_wins(all_pids):
''' Return list of all windows open under PID list
Currently unncessary because we work on active window '''
windows = []
for pid in all_pids:
all_lines = os.popen('xdotool search --pid ' + str(pid)). \
read().strip().splitlines
for l in all_lines():
windows.append(int(l))
return windows
def move_window(line, active_win):
''' Move window to x y coorindates on Desktop
If the letter x or y is passed, that dimension remains unchanged eg:
xdotool getactivewindow windowmove 100 100 # Moves to 100,100
xdotool getactivewindow windowmove x 100 # Moves to x,100
xdotool getactivewindow windowmove 100 y # Moves to 100,y
'''
line = ' '.join(line.split()) # Compress whitespace to single space
x = line.split(' ')[-2]
y = line.split(' ')[-1]
# We don't need to pass window ID as last active window defaults
all_lines = os.popen('xdotool getactivewindow windowmove ' + x + ' ' + y). \
read().strip().splitlines
for l in all_lines():
print(l)
def terminal_title(new_title):
''' Rather awkward calling xdotool which chokes on double quotes and bash
via python which chokes on backslashes.
Simple format (if it worked) would be:
command = r'PS1="${PS1/\\u@\\h: \\w/' + title + '}"'
The bash function copied from is:
function termtitle() { PS1="${PS1/\\u@\\h: \\w/$@}"; }
Reference for xdotool keycodes:
https://gitlab.com/cunidev/gestures/-/wikis/xdotool-list-of-key-codes
'''
title = new_title.split(' ', 1)[1] # Strip out leading "title" token
command = 'xdotool type PS1='
run_and_wait(command)
run_and_wait('xdotool key quotedbl')
command = 'xdotool type $'
run_and_wait(command)
run_and_wait('xdotool key braceleft')
command = 'xdotool type PS1/'
run_and_wait(command)
run_and_wait('xdotool key backslash')
run_and_wait('xdotool key backslash')
command = 'xdotool type u@'
run_and_wait(command)
run_and_wait('xdotool key backslash')
run_and_wait('xdotool key backslash')
command = 'xdotool type "h: "'
run_and_wait(command)
run_and_wait('xdotool key backslash')
run_and_wait('xdotool key backslash')
command = 'xdotool type "w/"'
run_and_wait(command)
command = 'xdotool type "' + title + '"'
run_and_wait(command)
run_and_wait('xdotool key braceright')
run_and_wait('xdotool key quotedbl')
run_and_wait('xdotool key Return')
def gedit():
last_modified_files = gedit_recent_files()
command = 'gedit '
for f in last_modified_files:
command=command+'"'
command=command+f
command=command+'" '
# Open gedit with last five modfied files
command=command+' &'
active_pid, active_win = launch_command(command)
if active_pid == 0:
print("ERROR launching", command, \
"Aborting 'dellstart' script")
exit()
def gedit_recent_files():
''' Get list of gedit 5 most recent files:
grep --no-group-separator -B5 'group>gedit' ~/.local/share/recently-used.xbel | sed -n 1~6p | sed 's# <bookmark href="file:///#/#g' | sed 's/"//g'
/home/rick/python/mmm added=2020-05-02T15:34:55Z modified=2020-11-19T00:43:45Z visited=2020-05-02T15:34:56Z>
/home/rick/python/mserve added=2020-07-26T16:36:09Z modified=2020-11-28T01:57:19Z visited=2020-07-26T16:36:09Z>
'''
command = "grep --no-group-separator -B5 'group>gedit' " + \
"~/.local/share/recently-used.xbel | " + \
"sed -n 1~6p | sed 's# <bookmark href=" + '"' + \
"file:///#/#g' | " + "sed 's/" + '"' + "//g'"
recent_files = []
times = []
all_lines = os.popen(command).read().strip().splitlines
uniquifier = 1 # gedit can give all open files same time
for l in all_lines():
fname = l.split(' added=', 1)[0]
trailing = l.split(' added=', 1)[1]
modified = trailing.split(' modified=', 1)[1]
modified = modified.split('Z', 1)[0]
# TODO: 2038
d = time.strptime(modified, '%Y-%m-%dT%H:%M:%S')
epoch = time.mktime(d)
epoch = int(epoch)
recent_files.append(fname)
try:
times.index(epoch)
# gedit has given multiple files the same modification time
epoch += uniquifier
uniquifier += 1
except:
pass # Not a duplicate time
times.append(epoch)
N=5
top_files = []
if N > len(times):
# Less than 5 most recent files in list
N = len(times)
if N == 0:
# No most recent files in list
return top_files # return empty list
# Store list in tmp to retrieve index
tmp=list(times)
# Sort list so that largest elements are on the far right
times.sort()
#print ('5 most recent from lists and indices')
for i in range(1, N+1):
top_files.append(recent_files[tmp.index(times[-i])])
return top_files
if __name__ == "__main__":
process_commands(commands)
# end of dellstart
Обратите внимание, что вам может потребоваться поработайте с переменной BASHRC_TIME
в вашей системе, чтобы программа работала быстрее. У меня в ~ / .bashrc
запущено множество функций, и ваш может работать намного быстрее.
Я планировал написать это много лет, но до сих пор не удосужился до него.