Программа, которая заканчивается, но никогда не заканчивается [закрыто]


35

Напишите программу, которая запускается сама по окончании.

Должно быть не более одного экземпляра программы, запущенной одновременно. Даже на малейший момент времени.

Вы можете игнорировать любой экземпляр, который пользователь запускает вручную во время вашего цикла. Но ваш код не должен делать это в цикле перезапуска.

Программа может запуститься через любой промежуток времени, если гарантируется, что она запустится снова.

Единственный способ остановить цикл - убить процесс.

Ваше решение не должно включать перезапуск среды (в которой запущена программа, включая ОС, компьютер, виртуальную машину, оболочку и т. Д.). Только ваша программа может быть перезапущена.


11
Разве это не то, что execделает в Linux?
Мниип

11
Я немного ленив, чтобы написать это прямо сейчас, но моя заявка будет (для окон): «Изменить реестр так, чтобы моя программа загружалась при запуске. Выполнить shutdown -r -t 0 -f».
Cruncher

3
Убить процесс не убьет ваш цикл, хотя.
микробиан

19
Я только что понял: если я хочу написать вирус и не знаю как, я мог бы 1) перейти в StackOverflow, спросить как. Получите ненависть от всех, и, вероятно, вопрос будет закрыт. Или 2) Идите к коду для гольфа, спросите других, как они это сделают. Получите несколько креативных ответов, и вопрос настолько популярен, что попадает в «горячий» список всей сети. Муа ха ха ха ха
rumtscho

5
@rumtscho Вы знаете, это хорошая общая стратегия. Хорошо, ребята, для моей следующей задачи, давайте посмотрим, кто может написать самую маленькую прошивку для прототипа устройства, сидящую на моем столе, которая отвечает всем требованиям в связанном документе. Чтобы оживить это, это должно быть сделано к 8:00 утра понедельника. Идти!
Джейсон С

Ответы:


50

Скрипт Bash, 3 символа (самый короткий, возможно, самый элегантный, хотя и по общему признанию спорный)

$0&

Просто помещает новый экземпляр себя в фоновом режиме (новый процесс), а затем выходит. Вероятно, новый экземпляр останется в очереди выполнения планировщика до тех пор, пока предыдущий экземпляр не будет создан.

Предупреждение - это сложно kill, так как PID постоянно меняется. Временное переименование файла сценария, вероятно, самый простой способ разорвать цикл.

Предполагается одноядерная система. Конечно, это нереально с Linux на современном железном железе, но его легко настроить при работе на виртуальной машине. Вероятно, мы могли бы добиться аналогичного tasksetэффекта, но это уменьшило бы влияние решения с тремя символами.

Этот ответ немного отклоняет правила в том смысле, что он применяет определенное значение «бег». Будут моменты, когда новый процесс был fork()отредактирован, а старый процесс все еще жив, т.е. может быть возможно наблюдать более одного PID. Однако новый процесс будет помещен в очередь выполнения планировщика Linux для ожидания циклов ЦП, в то время как существующий процесс продолжит выполняться. На данный момент все, что должно быть сделано существующим процессом, для bashсебя exit(). Это занимает ограниченное количество времени, хотя я довольно уверен, что это будет сделано гораздо раньше, чем будет сделан текущий квант временного интервала / планировщика. Подтверждением тому является тот факт, что bashна моей виртуальной машине запускается и выключается за 2 мс:

$ time bash -c:

реальный 0m0.002s
пользователь 0m0.000s
sys 0m0.000s
$ 

Еще одно подтверждающее доказательство того, что новый процесс на самом деле не выполняется до тех пор, пока не будет выполнен предыдущий процесс, можно увидеть в straceвыводе

strace -f -tt -o forever.strace bash -c ./forever.sh 

В выводе мы видим, что исходный процесс имеет PID 6929. Мы можем видеть fork()вызов (на самом деле clone()), который возвращает новый PID 6930. На данный момент есть 2 PID, но в настоящий момент работает только 6929:

6929 12: 11: 01.031398 клон (child_stack = 0, флаги = CLONE_CHILD_CLEARTID | CLONE_CHILD_SETTID | SIGCHLD, child_tidptr = 0x7f2f83ac49d0) = 6930
6929 12: 11: 01.031484 rt_sigprocmask (SIG_SETMASK, [], NULL, 8) = 0
6929 12: 11: 01.031531 rt_sigprocmask (SIG_BLOCK, [CHLD], [], 8) = 0
6929 12: 11: 01.031577 rt_sigprocmask (SIG_BLOCK, [CHLD], [CHLD], 8) = 0
6929 12: 11: 01.031608 rt_sigprocmask (SIG_SETMASK, [CHLD], NULL, 8) = 0
6929 12: 11: 01.031636 rt_sigprocmask (SIG_BLOCK, [CHLD], [CHLD], 8) = 0
6929 12: 11: 01.031665 rt_sigprocmask (SIG_SETMASK, [CHLD], NULL, 8) = 0
6929 12: 11: 01.031692 rt_sigprocmask (SIG_BLOCK, [CHLD], [CHLD], 8) = 0
6929 12: 11: 01.031726 rt_sigprocmask (SIG_SETMASK, [CHLD], NULL, 8) = 0
6929 12: 11: 01.031757 rt_sigprocmask (SIG_SETMASK, [], NULL, 8) = 0
6929 12: 11: 01.031803 rt_sigprocmask (SIG_BLOCK, NULL, [], 8) = 0
6929 12: 11: 01.031841 читать (255, "", 4) = 0
6929 12: 11: 01.031907 exit_group (0) =?
6930 12: 11: 01.032016 закрыть (255) = 0
6930 12: 11: 01.032052 rt_sigprocmask (SIG_SETMASK, [], NULL, 8) = 0

Полный straceвывод здесь.

Мы видим, что 6930 не выполняет никаких системных вызовов, пока 6929 полностью не завершится. Разумно предположить, что это означает, что 6930 вообще не работает, пока не закончится 6929. perfУтилита будет лучшим способом доказать это.


21
"перезапускается ..., затем выходит", поэтому одновременно запущено более одного экземпляра?
микробиан

4
«... на одном ядре» - да, я бы тоже так догадался. На многих ядрах вы, вероятно, сможете увидеть много.
blabla999

3
Если это было помечено code-golf, то это обязательно победит! +1
Джон Одом

3
@DigitalTrauma Вы делаете огромные предположения о том, сколько времени занимает bash, чтобы отключиться. top ничего не говорит - он обновляется только раз в несколько (десятки) секунд, но вы запускаете много процессов в секунду.
Дэвид Ричерби

2
@DavidRicherby - вы абсолютно правы - topэто не тот инструмент, который можно использовать здесь. Однако я вижу, что time bash -c :на моей виртуальной машине Ubuntu это занимает всего 2 мс, поэтому я не думаю, что было бы неразумно ожидать bashзавершения ее выключения до того, как будет произведен квант планирования.
Цифровая травма

26

Решение 1

PHP, 32 символа

Он отправляет заголовок, а затем останавливается. Через 3 секунды страница перезагружается.

файл a.php

header("Refresh: 3; url=a.php");

Это можно остановить, прекратив выполнение страницы перед отправкой заголовков, или просто убив браузер.


Решение 2

PHP, 2 страницы

Давайте рассмотрим два файла двух разных программ. Два файла находятся в одной папке.

файл a.php

header("Location:b.php");

файл b.php

header("Location:a.php");

Завершение одной из страниц перед отправкой заголовков завершает работу программы (также работает уничтожение браузера).

Вот та же программа в

ASP.NET

файл a.aspx

Response.Redirect("b.aspx")

файл b.aspx

Response.Redirect("a.aspx")

1
Это хорошее решение. Я надеюсь, что другие приходят с ответами, отличными от этого. Вот почему я сохранил это как конкурс популярности.
микробиан

Является ли ваш 3-секундный ответ перезагрузки действительным или нет, я оставляю его экспертам php. Я думаю, что это может быть действительным, потому что это браузер, который ждет не ваш PHP (я не эксперт).
микробиан

1
Хотя технически PHP запускается как модуль веб-сервера, а ваш веб-сервер не перезагружается, я думаю, что это допустимо, если вы рассматриваете файл .php как скрипт и скрипт запускается несколько раз.
TwiNight

@TwiNight Спасибо за отзыв, я ценю это :)
Vereos

2
Для вашего второго решения, не будет ли браузер обнаруживать цикл перенаправления и останавливаться самостоятельно? thedan1984.com/wp-content/uploads/2012/02/…
Ajedi32

19

ш

echo $PWD/$0 | at tomorrow

Это будет работать на любой Posix-совместимой системе.

Чтобы убить его, удалите файл или используйте atrm.


17

удар

exec "$0"

execзаменяет оболочку без создания нового процесса. Это гарантирует, что не может быть второго экземпляра.


1
Лучше вставь это ~/.bash_profile!
Yegle

@yegle: $0это -bashкогда .bash_profileисточник, так что это приведет к синтаксической ошибке.
Деннис

Ой, ты прав.
Yegle

exec ${0##-}в ~/.bash_profileработах :-)
yegle

14

Планировщик заданий Windows (собственный)

C ++. Кошмар программирования COM. Отвечает всем требованиям вызова.

#define _CRT_SECURE_NO_WARNINGS
#include <windows.h>
#include <taskschd.h>
#include <comutil.h>

#pragma comment(lib, "taskschd.lib")
#pragma comment(lib, "comsuppw.lib")    

static void timeplus (int seconds, char timestr[30]);


int main () {

    CoInitializeEx(NULL, COINIT_MULTITHREADED);
    CoInitializeSecurity(NULL, -1, NULL, NULL,
        RPC_C_AUTHN_LEVEL_PKT_PRIVACY,
        RPC_C_IMP_LEVEL_IMPERSONATE, NULL, 0, NULL);

    const char *name = "Restarter";

    char path[MAX_PATH + 1];
    GetModuleFileNameA(NULL, path, sizeof(path));
    path[sizeof(path) - 1] = 0; // workaround for xp

    ITaskService *taskman;
    CoCreateInstance(CLSID_TaskScheduler, NULL, CLSCTX_INPROC_SERVER,
        IID_ITaskService, (void **)&taskman);

    taskman->Connect(_variant_t(), _variant_t(), _variant_t(), _variant_t());

    ITaskFolder *root;
    taskman->GetFolder(_bstr_t("\\"), &root);

    // Delete the task.
    root->DeleteTask(_bstr_t(name), 0);

    // pause for 5 seconds to give user a chance to kill the cycle
    fprintf(stderr, "If you want to kill the program, close this window now.\n");
    Sleep(5000);
    fprintf(stderr, "Sorry, time's up, maybe next time.\n");

    // Create the task for 5 seconds from now.
    ITaskDefinition *task;
    taskman->NewTask(0, &task);

    IPrincipal *principal;
    task->get_Principal(&principal);
    principal->put_LogonType(TASK_LOGON_INTERACTIVE_TOKEN);

    ITaskSettings *settings;
    task->get_Settings(&settings);
    settings->put_StartWhenAvailable(VARIANT_TRUE);
    settings->put_DisallowStartIfOnBatteries(VARIANT_FALSE);
    settings->put_StopIfGoingOnBatteries(VARIANT_FALSE);

    ITriggerCollection *triggers;
    task->get_Triggers(&triggers);

    ITrigger *trigger;
    triggers->Create(TASK_TRIGGER_TIME, &trigger);

    char when[30];
    ITimeTrigger *trigger_time;
    trigger->QueryInterface(IID_ITimeTrigger, (void **)&trigger_time);
    trigger_time->put_Id(_bstr_t("TimeTrigger"));
    timeplus(10, when);
    trigger_time->put_StartBoundary(_bstr_t(when));
    timeplus(300, when);
    trigger_time->put_EndBoundary(_bstr_t(when));

    IActionCollection *actions;
    task->get_Actions(&actions);

    IAction *action;
    actions->Create(TASK_ACTION_EXEC, &action);

    IExecAction *action_exec;
    action->QueryInterface(IID_IExecAction, (void **)&action_exec);
    action_exec->put_Path(_bstr_t(path));

    IRegisteredTask *regtask;
    root->RegisterTaskDefinition(_bstr_t(name), task,
        TASK_CREATE_OR_UPDATE, _variant_t(), _variant_t(),
        TASK_LOGON_INTERACTIVE_TOKEN, _variant_t(""),
        &regtask);

    regtask->Release();
    action_exec->Release();
    actions->Release();
    trigger_time->Release();
    trigger->Release();
    triggers->Release();
    settings->Release();
    principal->Release();
    task->Release();
    root->Release();
    taskman->Release();
    CoUninitialize();

}


// outputs current utc time + given number of seconds as 
// a string of the form YYYY-MM-DDTHH:MM:SSZ
static void timeplus (int seconds, char timestr[30]) {

    SYSTEMTIME when;
    FILETIME whenf;
    LARGE_INTEGER tempval;

    GetSystemTimeAsFileTime(&whenf);
    tempval.HighPart = whenf.dwHighDateTime;
    tempval.LowPart = whenf.dwLowDateTime;
    tempval.QuadPart += seconds * 10000000LL; // 100 nanosecond units
    whenf.dwHighDateTime = tempval.HighPart;
    whenf.dwLowDateTime = tempval.LowPart;
    FileTimeToSystemTime(&whenf, &when);

    sprintf(timestr, "%04hu-%02hu-%02huT%02hu:%02hu:%02huZ",
        when.wYear, when.wMonth, when.wDay,
        when.wHour, when.wMinute, when.wSecond);

}

Скомпилируйте с MSVC (или MinGW GCC, если у вас есть все зависимости).

Программа запустится и зарегистрирует одноразовую задачу в планировщике задач Windows, чтобы запустить ее через 5 секунд (Панель управления -> Администрирование -> Планировщик задач для просмотра, задача называется «Перезагрузка»). Программа остановится на 5 секунд, чтобы дать вам шанс убить ее, прежде чем она создаст задачу.

Требования к соревнованиям:

  • Запускается снова, когда заканчивается. Да. Задача запланирована непосредственно перед выходом из программы.

  • Не более одного экземпляра программы, запущенной одновременно. Да. Программа завершается полностью и не запускается в течение 5 секунд. Запускается планировщиком.

  • Вы можете игнорировать любой экземпляр, который пользователь запускает вручную во время вашего цикла. Да, как побочный эффект от использования постоянного имени задачи.

  • Пока это гарантировано, что это начинается снова. Да, при условии, что Планировщик заданий работает (он находится в стандартной конфигурации Windows).

  • Единственный способ остановить цикл - убить процесс. Да, процесс может быть остановлен во время 5-секундного окна во время его работы. Программа удаляет задание до 5-секундной задержки, убивая его в это время, не оставит постороннее задание в планировщике.

  • Ваше решение не должно включать перезапуск среды. Да.

Кстати, если кто-то когда-нибудь задумывался над тем, почему приложения Windows были такими нестабильными (до появления .NET и C #), это одна из причин. Требуемый объем обработки ошибок (если бы я их включил), управление ресурсами и многословность создают ситуации, очень подверженные ошибкам, если программист даже немного ленив (немного выше кода очень ленив).

Гораздо проще и короче альтернатива, чтобы вызвать schtasks.exe. Я также представил версию с этим в сценарии .BAT .


13

BBC BASIC - дань Snow Patrol

Эмулятор на bbcbasic.co.uk

Это немного по-другому. Он печатает стих песни «Run» и играет арпеджио аккордов, чтобы вы могли подпевать. Это было вдохновлено тем фактом, что команда для выполнения (и, следовательно, последняя строка программы), конечно, RUN.

Все переменные очищаются в начале программы, поэтому для выбора следующего стиха требуется цвет экрана, оставленный предыдущей итерацией.

    5 C=POINT(0,0) MOD 4
   10 COLOUR 129+C
   15 CLS
   20 RESTORE 110+C
   25 READ A$
   30 PRINT A$
   35 FORK = 1 TO 4
   40   RESTORE K+100
   45   READ P
   50   FORM= 1 TO 8
   55     SOUND 1,-15,P,7
   60     SOUND 1,-15,P-20,7
   65   NEXT
   70 NEXT
  101 DATA 100
  102 DATA 128
  103 DATA 136
  104 DATA 120
  110 DATA Light up light up - As if you have a choice - Even if you can not hear my voice - I'll be right beside you dear.
  111 DATA Louder louder - And we'll run for our lives - I can hardly speak - I understand - Why you can't raise your voice to say.
  112 DATA Slower Slower - We dont have time for that - All I want is to find an easier way - To get out of our little heads.
  113 DATA Have heart my dear - We're bound to be afraid - Even if its just for a few days - Makin' up for all of this mess.
  120 RUN

ВЫХОД (монтаж 4 разных скриншотов)

введите описание изображения здесь


+1 за цветовое решение как альтернативу "разделяемой памяти".
Йоханнес Х.

11

HTML / JavaScript:

<form /><script>document.forms[0].submit()</script>

Код запускает уничтожение страницы, на которой он работает, а затем воссоздание другого экземпляра самого себя, когда браузер загружает страницу заново.

AFAIK, единственный выход - убить вкладку, на которой работает страница.

РЕДАКТИРОВАТЬ: в соответствии с популярным запросом, действительный код HTML5:

<!doctype html><meta charset=utf-8><title> </title><form></form>
<script>document.forms[0].submit()</script>

@JasonC Я не согласен. Я думаю, что разумные страницы должны соответствовать спецификациям, но конкурсы популярности вполне должны быть разумными, не так ли? : D так +1, мне очень нравится этот.
''

10

С

Эта программа действует как много вредоносных программ. Непосредственно перед закрытием он создает скрипт оболочки в каталоге / tmp. Он запускает сценарий оболочки, который позволяет исходной программе закрыть и отменить исходный PID. Через короткий промежуток времени (2 секунды) сценарий оболочки запускает новый процесс с программой. Для краткости местоположение программы жестко обозначено как «/ tmp / neverend /».

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>

void rebirth(){
    char t[] = "/tmp/pawnXXXXXX";
    char* pawnfile = mktemp(t);
    if(pawnfile){
        int fd = open(pawnfile, O_RDWR|O_CREAT);
        const char msg[]="sleep 2\n/tmp/neverend\n";
        if(fd>0){
            int n = write(fd, msg, sizeof(msg));
            close(fd);
            pid_t pid = fork();
            if(pid==0){
                char* args[3] = {"bash", pawnfile, NULL};
                execvp(args[0], args);
            }
        }
    }
}

int main(int argc, char* argv[]){
    printf("Starting %s\n", argv[0]);
    atexit(rebirth);
    printf("Exiting %s\n", argv[0]);
}

В каждый момент времени выполняется только один «бесконечный» процесс. Каждый новый процесс получает новый PID. Самый простой способ убить это - удалить исполняемый файл. Если вы хотите сделать его более злокачественным, вы можете скопировать как исполняемый файл, так и сценарий, чтобы в любой момент на диске было несколько копий программы.


1
Я ожидаю увидеть более инновационные ответы. См. Комментарии к вопросу о «дополнительных программах». Для меня дополнительная программа - это лишь часть вашей программы, которая висит рядом.
микробиан

4
Форкинг означает, что у вас будет два экземпляра процесса, запущенного одновременно, даже если они делают разные вещи.
Барри Фрутман

@BarryFruitman легко избежать, если использовать два разных исполняемых файла. Это действительно так, но не так элегантно.
Йоханнес Х.

Я полагаю, вы могли бы использовать, system()если правила не считают fork + exec /bin/shв качестве дополнительной программы.
Джейсон C

10

Perl

`perl -e"kill 9,$$"|perl $0`

Сценарий выдает системную команду, чтобы убить себя, и передать результат в другой экземпляр себя. Интерпретатор Perl используется для убийства по кросс-платформенным причинам.

Остановите безумие, удалив сценарий.


7

Atari 8-битный базовый

1L.:R.

Жетоны на:

1 LIST : RUN

Внутренне он очищает внутренние структуры, по сути стирая программу, прежде чем снова запустить ее из списка.

Это принципиально отличается от:

1L.:G.1

Который токенизирует:

1 LIST : GOTO 1

Это основной бесконечный цикл. Когда вы их запускаете, вы видите разницу в скорости (сначала медленнее).


Я не совсем понимаю, почему «список» во время выполнения программы очистил бы любые структуры кишечника. Я думаю, что у Atari есть буфер клавиатуры, так что можно было бы перечислить программу, нажать клавиши для ее запуска и выполнить «новое» с курсором, чтобы «перепечатать» его.
суперкат

@supercat - LIST нет, RUN делает.

По этой логике можно опустить «СПИСОК». С другой стороны, если бы программа заполнила буфер клавиатуры с несколькими возвратами каретки, поместила «NEW», затем программу и «RUN» в правильные места на экране, поместила курсор и вышла, она действительно стерла бы себя и перепечатывать себя автоматически.
суперкат

@supercat - без LIST, вы бы не увидели, что он работает. Я выбрал, LISTпотому что он имеет самый короткий вход L.. Мне нравится идея поместить это в буфер клавиатуры, это, конечно, достаточно коротко!

Я правильно помню, что Atari, как и компьютеры Commodore, читает текст с экрана, когда вы нажимаете Return? Насколько большой буфер клавиатуры? На VIC-20 и C64 это десять байтов. Программа, которая делает достаточно ударов для загрузки буфера клавиатуры, вероятно, не помещалась бы в буфер клавиатуры, но я написал программы, которые изменяли бы себя, печатая изменения на экране RUN, а затем добавляли несколько Returnнажатий клавиш. Такие вещи были особенно полезны на 64, так как у него не было команды [IIRC], которую INAtari имеет для слияния строк в программу.
Суперкат

5

На мейнфрейме IBM, работающем с z / OS, вы запускаете утилиту, которая копирует набор данных (файл) в другой набор данных (файл). Входные данные - это источник JCL (языка управления заданиями), который вы отправили для запуска. Выход - внутренний ридер (INTRDR). Вам также необходимо убедиться, что ваша система не позволяет запускать несколько идентичных имен заданий. Хорошо использовать класс заданий, у которого есть только один инициатор (место, где JOB может работать в пакетном режиме).

Там нет задействованных PID (в z / OS), поэтому не удается установить вызов.

Вы останавливаете процесс, сливая и / или промывая. Если что-то пошло не так, слив и / или промывка, ругань, удар ногой, попытка горячего старта и, наконец, холодный старт или нажатие на большую красную кнопку (и стрельба в программиста).

Я мог бы преувеличить по пути, но не пытайтесь это на работе ...

Пример использования SORT. Детали карты JOB зависят от сайта. Политика сайта может запрещать или запрещать использование INTRDR. Для использования INTRDR может потребоваться определенный класс. Если политика вашего сайта запрещает его использование , не используйте его, если вы не хотите взять свои вещи на прогулку в картонной коробке.

Хотя для INTRDR есть хорошие применения, не используйте его для этой цели . У тебя даже не будет возможности получить свою коробку.

//jobname JOB rest is to your site standards
//* 
//STEP0100 EXEC PGM=SORT 
//SYSOUT   DD SYSOUT=* 
//SORTOUT  DD SYSOUT=(,INTRDR) minimum required, site may require more 
//SYSIN    DD * 
  OPTION COPY 
//SORTIN   DD DISP=SHR,DSN=YOUR.LIBRARY.WITHJOB(JOBMEMBR) 

Другие утилиты доступны. Быструю программу было бы легко сделать, просто прочитайте файл, напишите файл.

Если вы хотите, чтобы пример этого был неправильным, попробуйте: http://ibmmainframes.com/viewtopic.php?p=282414#282414

Традиционный способ скопировать набор данных - это использовать служебную программу IBM IEBGENER, на которую ссылается Угорен в своем комментарии.

Однако в наши дни на многих сайтах IEBGENER будет добавлен псевдоним ICEGENER. ICEGENER, если сможет, будет использовать для копирования копию IBM DFSORT (или его конкурирующего SyncSort), потому что продукты SORT гораздо более оптимизированы для ввода-вывода, чем IEBGENER.

Я просто отключаю посредника, используя SORT.

Если вы работаете на сайте IBM Mainframe, вы знаете формат карты JOB, которую вам следует использовать. Минимальная JOB-карта, как я показал, без комментариев. Комментарий будет важен, потому что вы, возможно, должны предоставлять учетную информацию, например. Имя работы, скорее всего, будет иметь формат, специфичный для сайта.

Некоторые сайты запрещают или запрещают использование INTRDR. Быть в курсе

Некоторые сайты допускают одновременное выполнение нескольких заданий с одинаковым именем. Быть в курсе

Хотя, если вы не являетесь системным программистом, вы не можете создать такой класс, вам следует искать класс, который допускает только один инициатор. При этом процесс довольно безопасен - но будьте абсолютно уверены в том, что класс работает так, как описано. Тест. Не с этой работой.

Если вы являетесь системным программистом, вы знаете, что ничего не делаете за пределами своей компетенции. 'достаточно.

Если одно задание разрешено в одно и то же время и один инициатор, это будет постоянным потоком запуска / завершения следующего запуска / завершения следующего задания - до тех пор, пока вы не заполните катушку (еще одна плохая вещь) выводом из тысячи рабочих мест (или не хватает рабочих мест). Посмотрите консоль JES для предупреждений.

По сути, не делай этого. Если вы делаете это, не делайте этого на производственной машине.

Немного подведя итоги, я рассмотрю другой ответ о том, как это сделать в другой операционной системе IBM Mainframe: z / VSE ... z / VSE использует JCL. z / OS использует JCL. Они разные :-)


Идея выглядит хорошо, но это не ответ. Покажите нам JCL - JOB, EXEC и DD - тогда это будет ответом.
Угорен

Я долго не работал, поэтому я не уверен, что с этим делать. Если недостающие части являются просто локальной настройкой, тогда ОК. Но если вы прячете что-то, чтобы предотвратить злоупотребление, решитесь - публикуйте реальную вещь или ничего не публикуйте. PS Мы использовали IEBGENERтогда, чтобы просто скопировать.
Угорен

@ugoren Дальнейшее обновление, включая объяснение того, почему IEBGENER не был выбран для этой задачи. Удаление текста комментария в операторе JOB дает необходимый JCL для его запуска, но достаточность JCL зависит от стандартов локального сайта, либо от работы, либо от увольнения программиста.
Билл Вуджер

4

Python (72 байта)

import os
os.system('kill -9 %s && python %s' % (os.getpid(), __file__))

Я думаю, может быть меньше. Во-первых, путем жесткого кодирования имени файла (вместо использования __file__). Но здесь вы можете поместить этот код в файл и запустить его, как бы его ни звали :)


Вы, вероятно, можете изменить &&на &.
Hosch250

1
С каких это пор, user2509848?
Rhymoid

Ну, вы могли бы начать с удаления пробелов ...
Ry-

6
Так как он не помечен как code-golf , я буду хранить код следующим образом :-)
Maxime Lorant

4

Планировщик заданий Windows (.BAT)

Пакетный скрипт Windows. Отвечает всем требованиям вызова.

Насколько я вижу, это пока единственное решение для Windows, которое отвечает всем требованиям и не имеет нестандартных зависимостей (мое другое решение аналогично, но требует компиляции).

@ECHO OFF
SETLOCAL

schtasks /Delete /TN RestarterCL /F

ECHO Close this window now to stop.
TIMEOUT /T 5

FOR /f "tokens=1-2 delims=: " %%a IN ("%TIME%") DO SET /A now=%%a*60+%%b
SET /A start=%now%+1
SET /A starth=100+(%start%/60)%%24
SET /A startm=100+%start%%%60
SET /A end=%now%+3
SET /A endh=100+(%end%/60)%%24
SET /A endm=100+%end%%%60

schtasks /Create /SC ONCE /TN RestarterCL /RI 1 /ST %starth:~1,2%:%startm:~1,2% /ET %endh:~1,2%:%endm:~1,2% /IT /Z /F /TR "%~dpnx0"

ENDLOCAL

Программа ведет себя так же, как мой ответ C ++ / COM .

Программа запустится и зарегистрирует одноразовую задачу в планировщике задач Windows, которая запустится через 60 секунд (Панель управления -> Администрирование -> Планировщик задач для просмотра, задача называется «Перезагрузка»). Программа остановится на 5 секунд, чтобы дать вам шанс убить ее, прежде чем она создаст задачу.

Использует интерфейс командной строки Task Scheduler schtasks.exe. Арифметика в сценарии состоит в том, чтобы вычислять смещения времени, сохраняя время действительным и в формате ЧЧ: ММ.

Требования к соревнованиям:

  • Запускается снова, когда заканчивается. Да. Задача запланирована непосредственно перед выходом из программы.

  • Не более одного экземпляра программы, запущенной одновременно. Да. Программа завершается полностью и не работает в течение ~ 60 секунд. Запускается планировщиком.

  • Вы можете игнорировать любой экземпляр, который пользователь запускает вручную во время вашего цикла. Да, как побочный эффект от использования постоянного имени задачи.

  • Пока это гарантировано, что это начинается снова. Да, при условии, что Планировщик заданий работает и присутствует файл schtasks.exe (оба имеют значение true в конфигурациях Windows по умолчанию).

  • Единственный способ остановить цикл - убить процесс. Да, процесс может быть остановлен во время 5-секундного окна во время его работы. Программа удаляет задание до 5-секундной задержки, убивая его в это время, не оставит постороннее задание в планировщике.

  • Ваше решение не должно включать перезапуск среды. Да.

Примечание. Из-за ограниченного интерфейса командной строки время перезапуска должно быть указано в минутах, и задача не будет перезапущена на ноутбуках без подключенного адаптера переменного тока (извините).


3

Unix shell

Я еще не видел много решений, которые полагаются на несвязанную программу, чтобы перезапустить ее. Но это именно то, для чего at(1)была сделана утилита:

echo "/bin/sh $0"|at now + 1 minute

На самом деле трудно поймать, как работает программа, поскольку она запускается раз в минуту и ​​так быстро завершается. К счастью, atq(1)утилита покажет вам, что это все еще происходит:

$ atq
493     Fri Feb 21 18:08:00 2014 a breadbox
$ sleep 60
$ atq
494     Fri Feb 21 18:09:00 2014 a breadbox

И atrm(1)позволит вам разорвать цикл:

$ atq
495     Fri Feb 21 18:10:00 2014 a breadbox
$ atrm 495
$ atq

Вы можете заменить 1 minuteна 1 hour, или 1 week. Или дайте ему 1461 daysиметь программу, которая запускается раз в 4 года.


2

PowerShell

Я злоупотребляю (и, возможно, нарушаю) свое собственное правило.

[System.Threading.Thread]::Sleep(-1)

Требуется бесконечное количество времени, чтобы перезапустить себя.
Это можно убить, убив процесс хоста.

Просто подожди и увидишь ;)


5
+1 за креативность, но -1 за измену.
Йоханнес Х.

1
Ха, но "гарантировано ли, что оно начинается снова", если оно никогда не останавливается?
Джейсон C

Вот почему я сказал, что, возможно, нарушу правило. Это философская красота бесконечности, в которой можно предположить, что после этого может произойти все что угодно. Так работает машина Тьюринга.
микробиан

1
-100, потому что я не поддерживаю вас в победе в собственном конкурсе, особенно по техническим причинам, но +101, потому что ожидание его перезапуска - лучшее оправдание проволочек.
Джейсон C

Ну, вы знаете, тогда while true; do sleep 1; doneутешает, не так ли?
''

2

удар

echo -e "$(crontab -l)\n$(($(date "+%M")+1)) $(date '+%H %e %m * /repeat.sh')" | crontab -

Сохраните его как repeat.sh в каталоге / и дайте ему разрешение на выполнение. Это можно убить, удалив файл

Это работает, помещая запись в crontab, чтобы запустить ее через 1 минуту.


2

Visual Base 6 :)

Sub Main:Shell "cmd ping 1.1.1.1 -n 1 -w 500>nul&&"""&App.Path &"\"&App.EXEName& """":End Sub

Для запуска создайте новый проект, добавьте модуль с этим кодом, установите для объекта запуска «Sub Main», скомпилируйте и запустите исполняемый файл.


Более читаемая версия:

Sub Main()
    Call Shell("cmd ping 1.1.1.1 -n 1 -w 3000 > nul && """ & App.Path & "\" & App.EXEName & """")
End Sub

VB6 - это настоящий мужской VB. Последний в своем роде!
Джейсон C


1

удар

Дольше, чем должно быть, но я устал, и мне все равно :)

while true; do sleep 1; done; bash $0;

Вы сказали, что он должен перезапустить себя, когда закончится, вы не сказали, что он должен был делать это многократно или бесконечно. Кроме того, вы сказали, что никогда не должно быть запущено два экземпляра одновременно ... никогда не будет. ;)

Есть много способов сделать это. Моим личным фаворитом было бы сделать что-то вроде отправки пакета куда-то далеко, а затем (с помощью любого количества методов) получить ответ, запускающий процесс.


Технически sleepпроцесс возобновляется после его завершения
pastebin.com slash 0mr8spkT

Если программа - это программа, которая перезапускает себя самостоятельно , то подразумевается, что она должна делать это бесконечно - в противном случае она перезапускает что-то еще, что не является само собой.
Джейсон C

@ Джейсон C: Не слишком философски, насколько это возможно, он перезапускает себя. Мы могли бы обсудить, насколько сложным должно быть по-настоящему перезапустить себя , но я думаю, что это далеко за пределы того, что имел в виду автор. Хотя, если вы хотите, чтобы он действительно перезапустился сам, то, вероятно, будет что-то, что использует goto, или JMP, или любую другую конструкцию, которую может предложить ваш язык, чтобы вернуться к началу, так что это сам «перезапуск». В противном случае это просто выполнение чего-то, что отчетливо похоже на самого себя. Но тогда кто-то, скорее всего, возьмет на себя проблему, которая действительно не перезапускается Так что я отвлекся.
Ян Волшебник

1

Android: будильник перезапустит активность через 1 секунду

public class AutoRestart extends Activity
{

@Override
public void onCreate()
{
    finish();
}

@Override
public void onDestroy() {

    Intent restartServiceIntent = new Intent(getApplicationContext(), this.getClass());
    restartServiceIntent.setPackage(getPackageName());

    PendingIntent restartServicePendingIntent = PendingIntent.getService(getApplicationContext(), 1, restartServiceIntent, PendingIntent.FLAG_ONE_SHOT);
    AlarmManager alarmService = (AlarmManager) getApplicationContext().getSystemService(Context.ALARM_SERVICE);
    alarmService.set(
            AlarmManager.ELAPSED_REALTIME,
            SystemClock.elapsedRealtime() + 1000,
            restartServicePendingIntent);

    super.onDestroy();
}

}

1

C + MPI Environment

mpifork.c:

#include <stdio.h>

main(int argc, char * argv[])
{
    srand(time(NULL));
    int host = rand()%(argc-1)+1;
    FILE * logFile = fopen("mpifork.log", "a");
    if(logFile == NULL){
        fprintf(stderr, "Error: failed to open log file\n");
    } else {
        fprintf(logfile, "Jumping to %s\n", argv[host]);

        char * args[argc+5];
        args[0] = "mpirun";
        args[1] = "-H";
        args[2] = argv[host];
        args[3] = argv[0];
        for(host = 0; host < argc-1; host++) args[host+4] = argv[host+1];
        args[argc+3] = NULL;

        execvp("mpirun", args);
        fprintf(stderr, "exec died\n");
        perror("execvp");
    }
}

У вас должен быть установлен OpenMPI или другая реализация MPI. Компилировать с

mpicc -o mpifork mpifork.c

Теперь, когда я думаю об этом, нет никакой причины, по которой вы должны использовать mpicc-gcc или любой другой компилятор, который будет работать. Вы просто должны иметь mpirun.

gcc -o mpifork mpifork.c

Чтобы запустить его, вам, вероятно, следует указать полный путь и список хостов. Например, я добавил некоторые записи в / etc / hosts, которые все указывали на localhost, и запустил его так:

/home/phil/mpifork localhost localhost1 localhost2 localhost3 localhost4

Исполняемый файл должен находиться в том же каталоге на любом компьютере, на котором вы хотите его запустить.


По сути, это берет список хостов, предоставленных в командной строке, выбирает один из хостов и запускает исполняемый файл на целевом хосте с теми же аргументами. Если все идет отлично, mpirun будет вызывать себя снова и снова на разных машинах (или на одной и той же машине, если вы предоставите только localhost). Сам исполняемый файл (mpifork) завершается - после вызова execvpон больше не выполняется на первой машине.

Если вы хотите быть злым, вы можете вместо этого сделать этот запуск на каждой машине, включив полный список хостов, предоставленный в командной строке в args. Это снова и снова будет создавать свою копию на каждой машине - кластерную бомбу.

Тем не менее, в этой форме, я уверен, что это удовлетворяет правилам.


1

JavaScript

Без необходимости «заходить в сеть», когда в этом нет необходимости :-) Планирование цикла событий JavaScript позволяет нам писать программы, которые очень легко удовлетворяют заданным требованиям:

(function program() {
    // do what needs to be done
    setTimeout(program, 100);
})();

Это «перезапускает» programфункцию с частотой 10 раз в секунду. По своей природе JavaScript гарантирует, что одновременно будет выполняться только одна задача, и он не «перезапускает среду», как в «перезагрузке страницы».


0

Сборка x86

Не совсем уверен, что это соответствует вашим критериям, поскольку это не порождает новый процесс, но здесь это в любом случае.

Программа покажет окно сообщения, выделит некоторое количество памяти, скопирует свой собственный фрагмент кода в выделенную память и затем перейдет в это место, начиная цикл заново. Это должно работать, пока malloc не терпит неудачу.

format PE GUI 4.0
entry a

include 'include/win32a.inc'

section '.text' code readable executable

    a:
        push    0
        push    _caption
        push    _message
        push    0
        call    [MessageBoxA]

        push    b-a
        call    [malloc]

        push    b-a
        push    a
        push    eax
        call    [memcpy]

        call    eax
    b:

section '.data' data readable writeable

    _caption db 'Code challenge',0
    _message db 'Hello World!',0

section '.idata' import data readable writeable

    library user,'USER32.DLL',\
        msvcrt,'msvcrt.dll'

    import user,\
        MessageBoxA,'MessageBoxA'

    import msvcrt,\
        malloc,'malloc',\
        memcpy,'memcpy'

Составлено с помощью фасма.


4
Поскольку вызывать только что скопированный код является частью вашей программы, технически ваша программа никогда не завершается вообще.
микробиан

6
С точки зрения низкого уровня, то же самое можно сказать обо всех программах здесь. :-)
Брайан Кноблаух

@BrianKnoblauch Я не согласен. Наиболее интересные ответы здесь, похоже, изменяют системную среду, так что новая копия процесса запускается через некоторое время после уничтожения первой. Например, я думаю, что создание хрон-задания для запуска процесса в будущем было бы хорошим способом дать процессу полностью умереть, а затем перезапуститься.
Кевин - Восстановить Монику

2
@BrianKnoblauch Не совсем. Процесс представляет собой конструкцию операционной системы (которая в наши дни - как и с момента появления защищенного режима в 286 в 1982 году - также поддерживается аппаратными средствами через виртуальные адресные пространства и защищенную память). Когда это заканчивается, вся эта информация исчезает. Хотя это не было явно указано в запросе, я принимаю дух вызова в том смысле, что «перезапуск» подразумевает, что назначен новый идентификатор процесса.
Джейсон С

Что ж, я бы дал +1, если бы вам удалось освободить память в пути (пожалуйста, пропишите меня, как @только вы справитесь, так как я, вероятно, не буду следить за этим).
''

0

Linux upstart init

Учитывая строжайшее прочтение вопроса, я думаю, что это невозможно. По сути, это запрос на самопроизвольный запуск программы без помощи других запущенных программ.

Есть некоторые atи chronоснованные на ответах, но с самым строгим чтением, atdи anacronэто дополнительные программы, которые работают все время, поэтому они могут быть дисквалифицированы.

Связанный подход, но немного более низкий уровень - это использование Linux init. В качестве пользователя root добавьте этот файл .conf в /etc/init/:

описание "навсегда"

начать на уровне выполнения [2345]
остановитесь на уровне выполнения [! 2345]

респаун

Exec Sleep 10

Затем initперечитайте его .conf файлы:

sudo telinit 5

Это запустит sleepпроцесс, который будет жить 10 секунд, а затем выйдет. initзатем возродится, как sleepтолько он обнаружит, что предыдущий ушел.

Конечно, это все еще используется initв качестве дополнительной программы. Можно утверждать, что initэто логическое расширение ядра, которое всегда будет доступно в любом Linux.

Если это неприемлемо, то я думаю, что следующим шагом на более низком уровне будет создание модуля ядра, который запускает процесс пользовательского пространства (не уверен, насколько это просто). Здесь можно утверждать, что ядро ​​не является процессом и, следовательно, не является программой (дополнительной). С другой стороны, ядро ​​- это отдельная программа с точки зрения процессора.


-1

TI-BASIC: 5 символов

назови это prgmA

:prgmA

Я могу сосчитать 6 символов. Есть ли что-то особенное в подсчете размера программы TI-BASIC?
pastebin.com косая черта 0mr8spkT

Это :просто начало символа линии, когда вы программируете на TI-basic. Это не то, что вы вводите, а просто в редакторе.
scrblnrd3


Разве это не рекурсивный вызов? Попробуйте увеличить значение Aи использовать его в качестве базового варианта, в конце концов вы увидите, что оно выходит.
ζ--

Ну, все переменные являются глобальными в ti-basic, поэтому я не уверен. Это может быть
scrblnrd3
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.