Як запускати команди, як у черзі


42

Мені потрібно зробити багато копіювання різних файлів у різні папки. Я можу додати всі свої команди копіювання до скрипту bash, а потім запустити це, але тоді я повинен почекати, поки він закінчиться, якщо я хочу додати більше команд до цієї "черги копіювання".

Чи є спосіб я запускати команди як чергу та щось додати більше команд до цієї черги під час виконання завдань?

Пояснено по-іншому, я хочу розпочати тривале завдання. Хоча це працює, я хочу запустити ще один, який насправді не запускається, поки не буде зроблено перше. А потім додайте ще одну після цього останнього тощо. Чи можливо це якось можливо?


3
Я можу запропонувати вам прийняти відповідь, яка вирішує вашу проблему. Здається, є пара з них, яка б працювала на вас.
holmb

2
Так, може, і я цього хотів. Проблема в тому, що я запитав це, коли працював у компанії, яка використовувала Mac. Я більше не працюю там, і в мене немає ніяких Macs, тому я не можу перевірити жодне з них. Не відчуваю себе комфортно, якщо позначити одну як відповідь, коли я не в змозі перевірити, чи справді це працює, тому наразі я сподівався, що люди проголосують за ці відповіді, які їм знадобляться, тому "відповідь" може з'явитися таким чином. замість цього.
Свиш

Відповіді:


25

atУтиліта, найвідоміша для запуску команд в заданий час, також має функцію черги і може бути запропонована для запуску команди в даний час. Він читає команду для запуску зі стандартного вводу.

echo 'command1 --option arg1 arg2' | at -q myqueue now
echo 'command2 ...' | at -q myqueue now

batchКоманда еквівалентна at -q b -m now( -mтобто висновок команди, якщо такий є, буде відправлено по пошті до вас, як Хроні роблять). Не всі варіанти Unix підтримують назви черг ( -q myqueue); ви можете обмежитися однією чергою, яка називається b. Linux atобмежується однолітерними іменами черги.


2
Принаймні, на linux це, здається, не чекає завершення попередньої команди.
вд

@wds Працює для мене на Debian wheezy. Де і як це зламалось для вас? Зауважте, що лише чекає завершення команди; якщо команда запускає підпроцеси, які пережили їх батьків, при не чекає підпроцесів.
Жил 'ТАК - перестань бути злим'

Я спробував на CentOS 6. Я тестував просто простий "сон x". Я не впевнений, що робити, щоб це запустити, але я припускаю, що він запускає нижню частину, і її слід чекати результату (сплячий дзвінок не повертається одразу).
вд

Як і назви черг, "зараз" теж не виглядає стандартним: баш на ubuntu скаржиться на це ...
winwaed

@winwaed О, це now, ні -t now, вибачте. Я не помітив, що помилявся у зразковому коді.
Жил 'ТАК - перестань бути злим'

23

Додайте &до кінця вашої команди, щоб надіслати її на waitдругий план, а потім на ній, перш ніж виконувати наступну. Наприклад:

$ command1 &
$ wait; command2 &
$ wait; command3 &
$ ...

2
так! цей синтаксис є дивовижним, коли ти щось кинув, а потім переглянеш stackoverflow для того, щоб у черзі щось після цього
встановити

2
Якщо ви тим часом передумаєте про будь-яку з цих команд, що можна зробити, щоб перервати це wait? Це здається непрозорим для всіх моїх вбивств.
Кен Вільямс

1
Ти просто вбиваєш команду. waitПросто припиняє роботу до тих пір , поки попередні закінчити.
Герт Шондербі

Чи буде це працювати nohup?
Майкл

11

І рішення Бреда, і Манкоффа є гарними пропозиціями. Ще одна схожа на їх комбінацію - використання екрана GNU для реалізації вашої черги. Це має перевагу в тому, що ви можете запускатись у фоновому режимі, ви можете перевіряти його коли завгодно, а чергові нові команди просто вставляють їх у буфер, який слід виконати після виходу попередніх команд.

Спочатку запустіть:

$ screen -d -m -S queue

(до речі, зараз прийшов час пограти з чудовими. screenrc файлами )

Це породжує сеанс фонового екрану для вас з назвою черги.

Тепер викладіть у чергу стільки команд, скільки вам подобається:

screen -S queue -X stuff "echo first; sleep 4; echo second^M"

Я виконую кілька команд у вищевказаному лише для тестування. Ваш випадок використання, мабуть, буде схожий на:

screen -S queue -X stuff "echo first^M"
screen -S queue -X stuff "echo second^M"

Зауважте, що "^ M" у моєму рядку вище - це спосіб отримати вбудований новий рядок, який буде інтерпретовано пізніше після того, як екран введе його у вашу наявну оболонку bash. Використовуйте "CTL-V", щоб отримати цю послідовність.

Було б досить просто зробити кілька простих скриптів оболонок, щоб автоматизувати їх і встановити команди в чергу. Потім, коли ви хочете перевірити стан своєї фонової черги, ви повторно додаєте через:

screen -S queue -r

Технічно вам навіть не потрібно називати сеанс на екрані, і він буде добре працювати, але як тільки ви зачепите його, ви все одно хочете залишити його весь час. ;-)

Звичайно, якщо ви це зробите, ще один хороший спосіб зробити це - назвати одне з поточних вікон "чергою" та використовувати:

screen -S queue -p queue -X stuff "command"

Схоже, це в основному просто "набирає" команду під час сеансу запущеного екрану, так що коли оболонка знову отримає контроль після завершення першої команди, ця команда почнеться. Іншими словами, це еквівалентно рішення @ mankoff, але для введення тексту використовує більш чудовий інструмент.
Кен Вільямс

Досить багато - головна відмінність полягає в тому, що екранне рішення підтримує кращу автоматизацію. Деякі речі ви можете робити вручну, інші - за допомогою скриптів, і все це за допомогою простого інтерфейсу.
Йордан

@ Джордан Дуже добре, це працює для мене. Але що таке "речі" для після -X?
Костянтин

@Konstantin gnu.org/software/screen/manual/html_node/Paste.html#Paste (TL; DR - все, що випливає в термінал, як якщо б ви набрали його)
Йорданія,

@ Джордан О, я бачу зараз. Це команда. Я подумав, що це довільна рядок.
Костянтин

8

Є утиліта, яку я з великим успіхом використовував саме для випадку використання, який ви описуєте. Нещодавно я перенесла свій основний ноутбук на нове обладнання, яке передбачало переміщення деяких файлів до NAS, а решту - на нову машину.

Ось як я це зробив.

  1. Налаштуйте всі машини, задіяні в мережевому з'єднанні, щоб вони могли дістатися один до одного.

  2. На машині, з якої ви переміщуєте файли (надалі називається вихідною машиною), встановіть rsync з apt-get install rsyncтаємним соусом Task Spooler (веб-сайт http://vicerveza.homeunix.net/~viric/soft/ts/ ). Якщо ви перебуваєте на Debian, ім'я пакета для tsє, task-spoolerа виконуваний файл буде перейменований, tspщоб уникнути зіткнення імені з tsвиконуваним файлом з moreutilsпакету. Пакет Debian, пов'язаний з веб-сайту, ідеально встановлений на Ubuntu з dpkg -i task-spooler_0.7.3-1_amd64.debподібним або подібним.

  3. Також переконайтесь, що на всіх машинах встановлено SSH apt-get install openssh-server. На вихідній машині потрібно налаштувати SSH, щоб дозволити без пароля входити в цільові машини. Метод, який найбільше використовуватиме, - це аутентифікація з відкритим ключем ssh-agent(див. Https://www.google.se/search?q=ssh+public+key+authentication для прикладів цього), але я іноді використовую більш простий метод, який працює просто а також з автентифікацією пароля. Додайте наступне до конфігурації клієнта SSH (або ~/.ssh/configабо /etc/ssh/ssh_config):

    Host *
         ControlMaster auto
         ControlPath ~/.ssh/master-%r@%h:%p
    

    Потім відкрийте один термінал на вихідному апараті, увійдіть в систему ssh target1, автентифікуйтесь як зазвичай, а потім залиште цей термінал відкритим. Зауважте, що існує файл з сокетом з назвою ~/.ssh/master-user@target1:22, це файл, який буде тримати відкриту автентифіковану майстер-сесію відкритою і дозволять подальше наступне без паролів з'єднання user(доки для з'єднання використовуються однакові цільове ім'я хоста і порт).

    У цей момент вам потрібно переконатися, що ви можете увійти, не вимагаючи аутентифікації на цільових машинах.

  4. Тепер запустіть ts rsync -ave ssh bigfile user@target1:один файл або ts rsync -ave ssh bigdir user@target1:каталог. З функцією rsync важливо не включати в каталог (в bigdirпорівнянні з bigdir/) кінцеву косу рису, або rsync буде вважати, що ви мали на увазі еквівалент bigdir/*у більшості інших інструментів.

    Spooler Task поверне підказку і дозволить вам поставити в чергу багато цих команд послідовно. Перевірте чергу запуску tsбез аргументів.

Задач Spooler має безліч функцій, таких як перестановка черги запуску, запуск певної роботи лише в тому випадку, якщо інша робота успішно виконується тощо. Перегляньте довідку ts -h. Я інколи перевіряю вихід команди, коли він працює ts -c.

Існують і інші методи цього, але для вашого випадку використання вони включають Task Spooler. Я вирішую використовувати rsync через SSH для збереження часових міток файлів, копіювання яких через SMB не було б.


дякую за вашу відповідь, про яку я не знав ts, здається, дуже потужний і простий у використанні, просто роздвоєний на Github, автотолізований і дебіанізований.
Олексій

@ Алекс Я переглянув вашу вилку і особливо зацікавився тим, що було зроблено щодо автоматичного зачеплення та дебінізації оригінального джерела, і, переглядаючи ваші комісії, він не був доступний як відмінний від початкового джерела. Чи не заперечуєте ви, щоб натискати на нові коміти, які на кроці 1. імпортують оригінальне джерело та 2. здійснюють свої додатки? Це допоможе комусь переглядати ваш джерело, щоб (легше) довірити ваші доповнення до оригінального джерела. Це один з небагатьох пакетів, які я не встановлюю з PPA або подібного, тому було б непогано створити його самостійно за допомогою виделки.
holmb

ви знаєте, що я повинен змінити окуляри, я втратив частину вашої відповіді про існуючі task-spooler:-) ... все одно, це у вашому коментарі дуже гарна пропозиція, я зроблю дуже скоро.
Алекс

зробив, видалив і заново створив сховище з прогресивними коммітами, лише пару помилок (слід метаболізувати більше локальних комітетів перед натисканням)
Alex

4

Такі речі мені також потрібні досить часто. Я написав невелику утиліту, яка називається, afterяка виконує команду щоразу, коли закінчується якийсь інший процес. Це виглядає приблизно так:

#!/usr/bin/perl

my $pid = shift;
die "Usage: $0 <pid> <command...>" unless $pid =~ /^\d+$/ && @ARGV;

print STDERR "Queueing process $$ after process $pid\n";
sleep 1 while -e "/proc/$pid";
exec @ARGV;

Потім ви запускаєте його так:

% command1 arg1 arg2 ...  # creates pid=2853
% after 2853 command2 arg1 arg2 ... # creates pid=9564
% after 9564 command3 arg1 arg2 ...

Велика перевага цього перед деякими іншими підходами полягає в тому, що перше завдання не потрібно виконувати особливим чином, ви можете слідкувати за будь-яким процесом на своїй новій роботі.


Гарний сценарій @ken. Хоча я б рекомендував спробувати Spooler Task, оскільки вам, здається, потрібно час від часу цього вимагати. Дивіться мою відповідь.
holmb

Виглядає акуратно, дякую. Єдине, чого не вистачає ТС, - це здатність виконувати завдання, які не були розпочаті в рамках ТС. Хоча я здогадуюсь, ви могли б почати нову роботу з TS, мета якої - просто почекати завершення існуючого процесу.
Кен Вільямс

Справді. Це корисний аспект вашого рішення.
holmb

2

Command1 && Command2

  • "&&" означає, що command2 запускається лише після того, як команда1 закінчується з кодом повернення 0
  • Примітка: a || означає, що command2 запускається лише після того, як команда1 закінчується кодом повернення, відмінним від 0

1

Ви можете просто додати команди до командного рядка оболонки, який вже виконує команду.

Або введіть обережно, або введіть його в іншому місці, підтвердіть і виріжте та вставте. Навіть якщо поточна команда записує рядки виводу, ви все одно можете ввести щось нове, натисніть клавішу Enter, і вона запуститься, коли всі команди виконуються або введені до її завершення.

Приклад наступний. Ви можете вирізати і вставити все, або ввести наступні команди, коли працює 1-й (якщо ви вводите дійсно швидко), або, швидше за все, під час роботи другого.

echo "foo"
sleep 10; echo "bar"
sleep 3
echo "baz"

0

найскладніший спосіб, про який я можу придумати, - це підтримувати чергу "стан" за допомогою простих файлів блокування в / tmp. коли file1.sh виконує команди cp, він зберігатиме файл блокування (або тверду посилання) в / tmp. коли це буде зроблено, видаліть файл. кожен інший сценарій повинен буде шукати в / tmp для блокування файлів із вибраною схемою іменування. природно, це схильне до всіляких збоїв, але налаштовувати це неприємно і цілком можливо в межах баса.


Важко використовувати на практиці, оскільки вимагає, щоб кожне завдання, яке ви хочете виконати, потрібно змінити, щоб зберігати файли блокування, і потрібно знати (або приймати як параметри), які файли блокування використовувати. Коли це можливо, найкраще мати черги зовні до роботи.
Кен Вільямс
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.