Програма, яка закінчується, але ніколи не закінчується [закрито]


35

Напишіть програму, яка запускається знову після завершення.

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

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

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

Єдиний спосіб зупинити цикл - це вбити процес.

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


11
Це не лише те, що execробиться в Linux?
mniip

11
Мені трохи лінь писати це прямо зараз, але моє подання було б (для Windows): "Відредагуйте реєстр так, щоб моя програма завантажилась під час запуску. Запустіть shutdown -r -t 0 -f".
Cruncher

3
Вбивство процесу не вбиває ваш цикл.
мікробій

19
Я щойно зрозумів: якщо я хочу написати вірус і не знаю як, я міг би 1) перейти до StackOverflow, запитайте, як. Отримайте ненависть від усіх і, мабуть, питання буде закрито. Або 2) Перейдіть до коду гольфу, запитайте інших, як вони це зробили. Отримайте декілька творчих відповідей, і питання настільки популярне, що потрапляє до "гарячого" списку у всій мережі. Муа-ха-ха-ха.
румчо

5
@rumtscho Ви знаєте, це гарна загальна стратегія. Добре, хлопці, для мого наступного виклику давайте подивимось, хто може написати найменшу прошивку для прототипу пристрою, що сидить на моєму столі, який відповідає всім вимогам у пов'язаному документі. Щоб приправити це, це потрібно зробити до 8 ранку в понеділок. Ідіть!
Джейсон C

Відповіді:


50

Баш-сценарій, 3 символи (найкоротший, можливо, найелегантніший, хоча і, правда, суперечливий)

$0&

Просто розміщує новий екземпляр себе у фоновому режимі (новий процес), а потім виходить із системи. Новий екземпляр, ймовірно, залишиться в черзі виконання планувальника, поки не буде виконано попередній екземпляр.

Попередження - це важко kill, оскільки PID постійно змінюється. Тимчасове перейменування файлу сценарію - це, мабуть, найпростіший спосіб розірвати цикл.

Передбачається одноядерна система. Звичайно, це нереально для Linux на сучасному голому металевому обладнанні, але його легко налаштувати під час роботи в VM. Можливо, ми могли б досягти подібного трюку, використовуючи taskset, але це зменшило б вплив 3-char рішення.

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

$ час bash -c:

реальні 0м0.002с
користувач 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
Якщо на цьому позначено код-гольф, то це, безумовно, виграє! +1
Джон Одом,

3
@DigitalTrauma Ви робите величезні припущення щодо того, скільки часу потрібно, щоб башти закрилися. вгорі нічого не каже - він оновлюється лише раз на кілька (десятків) секунд, але ви нерестуєте багато процесів в секунду.
Девід Річербі

2
@DavidRicherby - ти абсолютно правий - topне є правильним інструментом для використання тут. Однак я бачу, що time bash -c :на мою програму Ubuntu VM потрібно лише 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 Дякую за відгук, я ціную це :)
Вереос,

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 (Native)

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 секунд (панель управління -> Адміністративні інструменти -> Планувальник завдань для перегляду, завдання має назву "Restarter"). Програма зробить паузу на 5 секунд, щоб дати шанс вбити її до того, як вона створить завдання.

Вимоги щодо виклику:

  • Починає знову, коли закінчує. Так. Завдання планується безпосередньо перед виходом з програми.

  • Не більше одного екземпляра програми, яка працює одночасно. Так. Програма завершується повністю і не працює 5 секунд. Його починає планувальник.

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

  • Поки гарантується, що він почнеться знову. Так, за умови запуску Планувальник завдань (він знаходиться в стандартній конфігурації Windows).

  • Єдиний спосіб зупинити цикл - це вбити процес. Так, процес може бути вбитий протягом 5 секундного вікна, поки він працює. Програма видаляє завдання до затримки на 5 секунд, вбивство її в цей час не залишить збитого завдання в планувальнику.

  • Ваше рішення не повинно включати перезапуск середовища. Так.

До речі, якщо хтось коли-небудь замислювався, чому програми Windows раніше були настільки нестабільними (до появи .NET і C #), це одна з причин. Необхідна кількість помилок (якщо я включив її), управління ресурсами та багатослівність створює дуже схильні до помилок ситуації, якщо програміст навіть найменший ледачий (вищезазначений код надзвичайно ледачий).

Набагато простішою та коротшою альтернативою є посилання на schtasks.exe. Я також подав свою версію в сценарії .BAT .


13

BBC BASIC - данина Сніговому патрулю

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

Цей дещо інший. Він друкує вірш пісні "Виконати" і відтворює арпеджіо акордів, щоб ви могли співати разом. Це було натхнене тим, що команда для виконання (а отже, і останній рядок програми) - це, звичайно, 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, єдиний вихід - це вбити вкладку, на якій працює сторінка.

EDIT: відповідно до популярного запиту, дійсний код 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
Форкінг означає, що у вас буде одночасно працювати два екземпляри процесу, навіть якщо вони роблять різні речі.
Barry Fruitman

@BarryFruitman легко уникнути, хоча реально використовувати два різні виконувані файли. Це дійсно тоді, але менш елегантно.
Йоганнес Х.

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

10

Perl

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

Сценарій видає системну команду вбити себе та передає результат в інший екземпляр себе. Інтерпретатор Perl використовується для вбивства з причин міжпланової.

Зупиніть безумство, видаливши сценарій.


7

8-розрядний Basic Atari

1L.:R.

Токенізує до:

1 LIST : RUN

Внутрішньо він очищає внутрішні структури, по суті витираючи програму, перш ніж запускати її знову з списку.

Це принципово відрізняється від:

1L.:G.1

Яке означення:

1 LIST : GOTO 1

Це основна нескінченна петля. Запускаючи їх, ви бачите різницю в швидкості (спочатку повільніше).


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

@supercat - СПИСОК не робить, RUN робить.

За цією логікою можна було опустити "СПИСОК". З іншого боку, якщо програма заповнила буфер клавіатури, за допомогою декількох повернень каретки, поставте "НОВО", а потім програму та "РУН" у потрібних місцях на екрані, наведіть курсор і вийдете, воно справді стерне себе і повторно вводити себе автоматично.
supercat

@supercat - без цього LISTви б не бачили, що він працює. Я вибрав, LISTтому що він має найкоротший вклад L.. Мені подобається ідея помістити це в буфер клавіатури, це, звичайно, досить коротко!

Чи правильно я пам’ятаю, що Atari, як і машини Commodore, читає текст із екрану, коли ви натискаєте Return? Наскільки великий буфер клавіатури? На VIC-20 та C64 - це десять байт. Програма, яка робить достатньо натискань для завантаження буфера клавіатури, ймовірно, не впишеться в буфер клавіатури, але я написав програми, які могли б змінити себе, надрукувавши зміни на екрані, за якими слід RUN, і нанести кілька Returnнатискань клавіш. Такі речі були особливо корисні для 64, оскільки в ній не було команди [IIRC], INяку Atari має для об'єднання ліній у програму.
supercat

5

У IBM Mainframe, що працює з z / OS, ви запускаєте утиліту, яка копіює набір даних (файл) в інший набір даних (файл). Вхід - це джерело представленої вами програми JCL (Мова управління роботою), яка викликає її запуск. Вихід - внутрішній зчитувач (INTRDR). Вам також потрібно буде переконатися, що ваша система не дозволяє виконувати декілька однакових імен завдань. Добре використовувати клас роботи, який має лише одного ініціатора (місце, де РОБОТА може працювати в пакетному режимі).

Ні 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, якщо зможе, скористається DFSORT IBM (або його конкурента SyncSort), щоб зробити копію, оскільки продукти SORT значно оптимізовані для IO, ніж IEBGENER.

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

Якщо ви працюєте на сайті IBM Mainframe, ви знаєте формат 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?
Римоїд

Ну, можна почати з видалення пробілів…
Ри-

6
Оскільки він не позначений кодом-гольф , я збережу код так :-)
Максим Лорант

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 секунд пізніше (Панель керування -> Адміністративні інструменти -> Планувальник завдань для перегляду, завдання називається "Restarter"). Програма зробить паузу на 5 секунд, щоб дати вам шанс її вбити до того, як вона створить завдання.

Використовує інтерфейс планувальника завдань командного рядка schtasks.exe. Арифметика в сценарії полягає в обчисленні компенсацій часу, зберігаючи дійсний час і у форматі HH: MM.

Вимоги щодо виклику:

  • Починає знову, коли закінчує. Так. Завдання планується безпосередньо перед виходом з програми.

  • Не більше одного екземпляра програми, яка працює одночасно. Так. Програма завершується повністю і не працює протягом ~ 60 секунд. Його починає планувальник.

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

  • Поки гарантується, що він почнеться знову. Так, за умови запуску планувальника завдань та присутності schtasks.exe (обидва вірні в конфігураціях Windows за замовчуванням).

  • Єдиний спосіб зупинити цикл - це вбити процес. Так, процес може бути вбитий протягом 5 секундного вікна, поки він працює. Програма видаляє завдання до затримки на 5 секунд, вбивство її в цей час не залишить збитого завдання в планувальнику.

  • Ваше рішення не повинно включати перезапуск середовища. Так.

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


3

Оболонка Unix

Я ще не бачив багатьох рішень, які покладаються на незв'язану програму для її перезавантаження. Але саме для цього 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 -

Збережіть це як файл repe.sh у каталозі / та дайте йому дозвіл на виконання. Його можна вбити, видаливши файл

Це спрацьовує, поставивши запис у crontab, щоб запустити його через 1 хвилину.


2

Візуальна база 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

@Jason C: Без надто філософського, наскільки це можливо, він перезапускається сам. Ми можемо обговорити, наскільки складним має бути справжній перезапуск самостійно , але я думаю, що це далеко поза тим, що мав на увазі автор. Хоча, якщо ви хочете, щоб він по-справжньому перезапустив себе, тоді, ймовірно, буде щось, що використовує goto, або JMP, або будь-яку конструкцію, яку може запропонувати ваша мова, повернутися до початку, тому це "перезапуск" сам по собі. В іншому випадку це просто виконання чогось, що виразно схоже на себе. Але тоді хтось, швидше за все, сприйме питання, що це неправда перезапуск. Тож я відволікаюсь.
Ian Wizard

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

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. Це дозволило б повторно створити копію себе на кожній машині, знову і знову - кластерної forkbomb.

Однак у цій формі я майже впевнений, що це відповідає правилам.


1

JavaScript

Без необхідності "зайти в мережу", коли це не потрібно :-) Планування циклу подій JavaScript дозволяє нам дуже легко писати програми, які відповідають заданим вимогам:

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

Це "перезапускає" programфункцію 10 разів на секунду. Природою JavaScript гарантується, що одночасно буде виконуватися лише одне завдання, і воно не «перезапустить середовище», як при «перезавантаженні сторінки».


0

x86 Збірка

Не зовсім впевнений, що це відповідає вашим критеріям, оскільки він не породив новий процес, але ось він все одно.

Програма покаже вікно повідомлень, виділить деяку пам’ять, скопіює власний розділ коду у виділену пам’ять, а потім перейде до цього місця, починаючи цикл. Він повинен працювати, поки не вийде з ладу.

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 році - також підтримується обладнанням за допомогою віртуальних адресних просторів та захищеної пам'яті). Коли це закінчиться, вся ця інформація пропадає. Хоча це не було чітко зазначено в виклику, я вважаю, що «дух перезапуску» означає, що «перезапуск» означає, що призначений новий ідентифікатор процесу.
Джейсон C

Ну, я б дав +1, якщо вам вдасться звільнити пам'ять по дорозі (будь-ласка, напишіть мені, @як тільки ви керуєте, оскільки я, швидше за все, не зважаю на це).
yo

0

Linux upstart init

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

Є деякі atі chron-и відповіді, але при строгому читанні, atdі anacronє додатковими програмами, які виконуються весь час, так що вони можуть бути дискваліфіковані.

Пов'язаний підхід, але трохи нижчий рівень - це використання Linux init. Як корінь, додайте цей .conf файл у /etc/init/:

опис "назавжди"

старт на рівні бігу [2345]
зупинка на пробігу [! 2345]

відроджена

виконувати сон 10

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

sudo telinit 5

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

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

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


-1

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

назви це prgmA

:prgmA

Я можу порахувати 6 символів. Чи є щось особливе у підрахунку розміру програми TI-BASIC?
pastebin.com slash 0mr8spkT

Це :лише початок символу рядка, коли ви програмуєте в TI-basic. Це не те, що ви вводите, це просто там у редакторі.
scrblnrd3

Я бачу, дякую за інформацію
pastebin.com slash 0mr8spkT

Це не рекурсивне виклик? Спробуйте збільшити Aі використовувати значення цього значення в якості базового випадку, ви побачите, що воно виходить з часом.
ζ--

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