โปรแกรมที่จบลง แต่ไม่สิ้นสุด [ปิด]


35

เขียนโปรแกรมที่เริ่มตัวเองอีกครั้งเมื่อเสร็จสิ้น

ไม่ควรมีมากกว่าหนึ่งอินสแตนซ์ของโปรแกรมที่ทำงานในเวลาเดียวกัน ไม่แม้แต่สักครู่ของเวลา

คุณสามารถละเว้นอินสแตนซ์ใด ๆ ที่เริ่มต้นโดยผู้ใช้ด้วยตนเองในระหว่างรอบของคุณ แต่รหัสของคุณไม่ควรทำในรอบการรีสตาร์ทของคุณ

โปรแกรมสามารถเริ่มหลังจากเวลาใดก็ได้ตราบใดที่มีการรับประกันว่าจะเริ่มอีกครั้ง

วิธีเดียวที่จะหยุดวงจรคือการฆ่ากระบวนการ

โซลูชันของคุณไม่ควรเกี่ยวข้องกับการรีสตาร์ทสภาพแวดล้อม (ซึ่งโปรแกรมกำลังทำงานอยู่รวมถึงระบบปฏิบัติการ, เครื่อง, VM, เชลล์ ฯลฯ ) เฉพาะโปรแกรมของคุณที่ได้รับอนุญาตให้รีสตาร์ท


11
นี่ไม่ใช่execลินุกซ์หรือเปล่า?
mniip

11
ฉันขี้เกียจนิดหน่อยที่จะเขียนมันตอนนี้ แต่การส่งของฉันจะเป็น (สำหรับ windows): "แก้ไขรีจิสทรีเพื่อให้โปรแกรมของฉันบูตเมื่อเริ่มต้นใช้งานshutdown -r -t 0 -f"
Cruncher

3
การฆ่ากระบวนการจะไม่ฆ่าวัฏจักรของคุณ
microbian

19
ฉันเพิ่งรู้ว่า: ถ้าฉันต้องการเขียนไวรัสและไม่รู้วิธีฉันสามารถ 1) ไปที่ StackOverflow ถามได้อย่างไร รับความเกลียดชังจากทุกคนและอาจปิดคำถาม หรือ 2) ไปที่โค้ดกอล์ฟถามคนอื่นว่าพวกเขาทำได้อย่างไร รับคำตอบที่สร้างสรรค์เพื่อเลือกสรรและคำถามดังกล่าวจึงได้รับความนิยมในรายการ "ร้อน" ทั่วทั้งเครือข่าย เฮ้ยฮ่าฮ่าฮ่า
rumtscho

5
@rumtscho คุณรู้ไหมว่าเป็นกลยุทธ์ทั่วไปที่ดี โอเคสำหรับความท้าทายต่อไปของฉันมาดูกันว่าใครสามารถเขียนเฟิร์มแวร์ที่เล็กที่สุดสำหรับอุปกรณ์ต้นแบบที่วางอยู่บนโต๊ะของฉันซึ่งตรงตามข้อกำหนดทั้งหมดในเอกสารที่เชื่อมโยง ในการปรุงรสด้วยวิธีนี้จะต้องทำก่อน 8 โมงเช้าวันจันทร์ ไป!
Jason C

คำตอบ:


50

Bash script, 3 chars (สั้นที่สุดอาจเป็นสง่าที่สุดแม้ว่าจะเป็นที่ถกเถียงกันมาก)

$0&

เพียงวางอินสแตนซ์ใหม่ของตัวเองในพื้นหลัง (กระบวนการใหม่) จากนั้นออก อินสแตนซ์ใหม่ที่มีแนวโน้มจะยังคงอยู่ในตัวจัดกำหนดการรันคิวจนกว่าอินสแตนซ์ก่อนหน้านี้จะทำ

คำเตือน - เป็นการยากkillที่ PID จะเปลี่ยนแปลงอย่างต่อเนื่อง การเปลี่ยนชื่อไฟล์สคริปต์ชั่วคราวอาจเป็นวิธีที่ง่ายที่สุดในการทำลายวงจร

สันนิษฐานว่าเป็นระบบแกนเดียว แน่นอนว่านี่ไม่ใช่ความจริงกับ Linux บนฮาร์ดแวร์โลหะเปลือยที่ทันสมัย ​​แต่สามารถกำหนดค่าได้อย่างง่ายดายเมื่อทำงานใน VM เราอาจจะประสบความสำเร็จในการใช้กลอุบายที่คล้ายกันtasksetแต่นั่นจะลดผลกระทบของโซลูชัน 3 char

คำตอบนี้โค้งกฎเล็กน้อยในที่มันใช้ความหมายเฉพาะของ "ทำงาน" จะมีช่วงเวลาที่กระบวนการใหม่ได้รับการfork()แก้ไขและกระบวนการเก่ายังคงมีอยู่ - เช่นอาจเป็นไปได้ที่จะสังเกต PID มากกว่าหนึ่ง อย่างไรก็ตามกระบวนการใหม่จะถูกวางในรันไทม์คิวของตัวจัดกำหนดการ Linux เพื่อรอรอบ CPU ในขณะที่กระบวนการที่มีอยู่จะยังคงดำเนินการต่อไป ณ จุดนี้สิ่งที่ต้องทำตามกระบวนการที่มีอยู่สำหรับตัวเองไปbash exit()การดำเนินการนี้ใช้เวลาค่อนข้าง จำกัด แต่ฉันค่อนข้างมั่นใจว่าจะทำได้ก่อนที่จะมีการทำควอนตัมครั้ง / ตารางเวลาปัจจุบัน หลักฐานสนับสนุนคือความจริงที่bashเริ่มขึ้นและปิดตัวลงใน 2ms บน VM ของฉัน:

$ time bash -c:

จริง 0m0.002s
ผู้ใช้ 0m0.000s
ระบบ 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)
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
"รีสตาร์ท ... จากนั้นออก" ดังนั้นมีมากกว่าหนึ่งอินสแตนซ์ที่ทำงานพร้อมกันหรือไม่
microbian

4
"... บนแกนเดียว" - ใช่ฉันก็เดาเช่นกัน ในหลายคอร์คุณอาจเป็นไปได้ที่จะเห็นหลาย ๆ
blabla999

3
ถ้านี่คือการติดแท็กรหัสกอล์ฟแล้วนี่จะชนะแน่นอน! +1
John Odom

3
@DigitalTrauma คุณกำลังตั้งสมมติฐานอย่างมากเกี่ยวกับระยะเวลาที่ใช้ในการทุบตีเพื่อปิดตัวเอง ด้านบนไม่บอกอะไรคุณ - มันอัปเดตทุกๆสองสาม (สิบ) วินาที แต่คุณกำลังวางไข่กระบวนการหลายต่อวินาที
David Richerby

2
@DavidRicherby - คุณอย่างถูก - topไม่ได้เป็นเครื่องมือที่เหมาะสมที่จะใช้ที่นี่ อย่างไรก็ตามฉันเห็นว่าtime bash -c :ใช้เวลาเพียง 2ms บน Ubuntu VM ของฉันดังนั้นฉันจึงไม่คิดว่ามันจะไม่มีเหตุผลที่คาดว่าbashจะปิดการทำงานให้เสร็จสมบูรณ์ก่อนที่จะทำการตั้งเวลาควอนตัม
Digital Trauma

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
นั่นเป็นทางออกที่ดี ฉันหวังว่าคนอื่นจะได้คำตอบที่แตกต่างกว่านี้ นั่นเป็นเหตุผลที่ฉันเก็บไว้เป็นการประกวดความนิยม
microbian

ไม่ว่าคำตอบการรีโหลด 3 วินาทีของคุณนั้นถูกต้องหรือไม่ฉันปล่อยให้ผู้เชี่ยวชาญ php ฉันคิดว่ามันอาจจะใช้ได้เพราะเป็นเบราว์เซอร์ที่ไม่รอ php ของคุณ (ฉันไม่มีผู้เชี่ยวชาญ)
microbian

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 task scheduler เพื่อเริ่มต้นเอง 5 วินาทีต่อมา (แผงควบคุม -> เครื่องมือการดูแลระบบ -> Task Scheduler เพื่อดูงานจะมีชื่อว่า "Restarter") โปรแกรมจะหยุดเป็นเวลา 5 วินาทีเพื่อให้คุณมีโอกาสฆ่ามันก่อนที่จะสร้างงาน

ข้อกำหนดในการท้าทาย:

  • เริ่มต้นตัวเองอีกครั้งเมื่อเสร็จสิ้น ใช่. งานถูกกำหนดไว้ก่อนที่โปรแกรมจะออก

  • ไม่มีมากกว่าหนึ่งอินสแตนซ์ของโปรแกรมที่ทำงานในเวลาเดียวกัน ใช่. ออกจากโปรแกรมอย่างสมบูรณ์และไม่ทำงานเป็นเวลา 5 วินาที มันเริ่มจากตัวกำหนดตารางเวลา

  • คุณสามารถละเว้นอินสแตนซ์ใด ๆ ที่เริ่มต้นโดยผู้ใช้ด้วยตนเองในระหว่างรอบของคุณ ใช่เป็นผลข้างเคียงของการใช้ชื่อภารกิจคงที่

  • ตราบใดที่มันรับประกันว่ามันจะเริ่มขึ้นอีกครั้ง ใช่โดยที่ Task Scheduler กำลังทำงาน (อยู่ในการกำหนดค่า Windows มาตรฐาน)

  • วิธีเดียวที่จะหยุดวงจรคือการฆ่ากระบวนการ ใช่กระบวนการสามารถถูกฆ่าได้ในช่วง 5 วินาทีขณะที่มันกำลังทำงาน โปรแกรมจะลบงานก่อนที่จะมีการหน่วงเวลา 5 วินาทีการฆ่ามันในเวลานี้จะไม่ปล่อยให้งานหลงทางอยู่ในตัวกำหนดตารางเวลา

  • โซลูชันของคุณไม่ควรเกี่ยวข้องกับการรีสตาร์ทสภาพแวดล้อม ใช่

อย่างไรก็ตามถ้าใครเคยสงสัยว่าทำไมแอปพลิเคชัน Windows ที่เคยมีความไม่เสถียร (ก่อนการกำเนิดของ. NET และ C #) นี่เป็นเหตุผลหนึ่งที่ทำไม จำนวนของการจัดการข้อผิดพลาดที่จำเป็น (ถ้าฉันรวมไว้) การจัดการทรัพยากรและการใช้คำฟุ่มเฟื่อยตั้งสถานการณ์ที่เกิดข้อผิดพลาดได้ง่ายมากหากโปรแกรมเมอร์นั้นแม้แต่คนที่ขี้เกียจนิดหน่อย

ทางเลือกที่ง่ายและสั้นกว่ามากคือการเรียกใช้ schtasks.exe ฉันได้ส่งเวอร์ชันที่มีในสคริปต์. BATเช่นกัน


13

BBC BASIC - ส่วยให้ Snow Patrol

Emulator ที่ 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 สำหรับโซลูชันสีเป็นทางเลือก "หน่วยความจำที่แชร์"
Johannes H.

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 ดังนั้นฉันชอบอันนี้มาก
yo '22

10

C

โปรแกรมนี้ทำหน้าที่เหมือนมัลแวร์จำนวนมาก ก่อนที่มันจะปิดมันจะสร้างเชลล์สคริปต์ในไดเร็กทอรี / 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
ฉันคาดว่าจะเห็นคำตอบที่เป็นนวัตกรรมมากขึ้น ดูความคิดเห็นสำหรับคำถามเกี่ยวกับ 'โปรแกรมเสริม' สำหรับฉันโปรแกรมเสริมเป็นเพียงส่วนหนึ่งของโปรแกรมของคุณ
microbian

4
ทางแยกหมายถึงคุณจะมีสองอินสแตนซ์ของกระบวนการทำงานในเวลาเดียวกันแม้ว่าพวกเขากำลังทำสิ่งต่าง ๆ
Barry Fruitman

@BarryFruitman ง่ายต่อการหลีกเลี่ยงแม้ว่าโดยการใช้สองโปรแกรมที่แตกต่างกันจริงๆ มันถูกต้องแล้ว แต่ก็ดูสง่างามน้อยลง
Johannes H.

ฉันคิดว่าคุณสามารถใช้system()หากกฎไม่นับ fork + exec /bin/shเป็นโปรแกรมเสริม
Jason C

10

Perl

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

สคริปต์ออกคำสั่งระบบเพื่อฆ่าตัวเองและไพพ์ผลลัพธ์ลงในอินสแตนซ์อื่นของตัวเอง ล่าม Perl ใช้เพื่อทำการฆ่าเพื่อเหตุผลข้ามแพลตฟอร์ม

หยุดความบ้าด้วยการลบสคริปต์


7

Atari 8-bit Basic

1L.:R.

โทเค็นเป็น:

1 LIST : RUN

ภายในเป็นการล้างโครงสร้างภายในโดยหลักแล้วเป็นการลบโปรแกรมก่อนที่จะรันอีกครั้งจากรายชื่อ

นี่คือพื้นฐานที่แตกต่างจาก:

1L.:G.1

ซึ่งโทเค็นเพื่อ:

1 LIST : GOTO 1

นี่คือการวนซ้ำไม่สิ้นสุดพื้นฐาน เมื่อคุณรันมันคุณจะเห็นความแตกต่างของความเร็ว (ก่อนจะช้ากว่า)


ฉันไม่ชัดเจนว่าทำไม "รายการ" ระหว่างการดำเนินการโปรแกรมจะล้างโครงสร้าง interenal ฉันคิดว่า Atari มีบัฟเฟอร์แป้นพิมพ์ดังนั้นจึงสามารถแสดงรายการโปรแกรมสิ่งที่กดแป้นพิมพ์เพื่อเรียกใช้และทำ "ใหม่" โดยมีเคอร์เซอร์วางไว้ที่ตำแหน่ง "พิมพ์ซ้ำ"
supercat

@supercat - รายการไม่ได้ RUN ทำ

โดยตรรกะนั้นเราสามารถละเว้น "LIST" ในทางกลับกันหากโปรแกรมยัดบัฟเฟอร์ของคีย์บอร์ดด้วยการคืนค่าขนส่งสองสามครั้งให้ใส่ "ใหม่" ตามด้วยโปรแกรมและ "RUN" ที่จุดขวาบนหน้าจอเลื่อนเคอร์เซอร์และออกจากโปรแกรมมันจะลบตัวมันเองอย่างแท้จริง และพิมพ์ตัวเองอีกครั้งโดยอัตโนมัติ
supercat

@supercat - หากไม่มีLISTคุณจะไม่เห็นว่ามันกำลังทำงานอยู่ ผมเลือกเพราะมีการป้อนข้อมูลที่สั้นที่สุดLIST L.ฉันชอบความคิดในการใส่ลงในบัฟเฟอร์ของแป้นพิมพ์มันสั้นพอที่แน่นอน!

ฉันจำได้ถูกต้องหรือไม่ว่า Atari เหมือนเครื่อง Commodore อ่านข้อความจากหน้าจอเมื่อคุณกดReturn? บัฟเฟอร์ของคีย์บอร์ดมีขนาดใหญ่แค่ไหน? บน VIC-20 และ C64 มันคือสิบไบต์ โปรแกรมที่มีแรงกระตุ้นพอที่จะโหลดบัฟเฟอร์ของแป้นพิมพ์อาจจะไม่พอดีกับบัฟเฟอร์ของแป้นพิมพ์ แต่ฉันได้เขียนโปรแกรมที่จะแก้ไขตัวเองโดยการพิมพ์การเปลี่ยนแปลงไปยังหน้าจอตามด้วยRUNการReturnกดแป้นบางครั้ง สิ่งดังกล่าวมีประโยชน์อย่างยิ่งใน 64 เนื่องจากไม่มีINคำสั่ง[IIRC] ที่อาตาริมีสำหรับการรวมสายเข้ากับโปรแกรม
supercat

5

บน IBM Mainframe ที่รัน z / OS คุณรันยูทิลิตีซึ่งคัดลอกชุดข้อมูล (ไฟล์) ไปยังชุดข้อมูลอื่น (ไฟล์) อินพุตเป็นแหล่งที่มาของ JCL (ภาษาควบคุมงาน) ที่คุณส่งเพื่อให้ทำงาน เอาต์พุตคือ Internal Reader (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 เช่นเดียวกับ ugoren alludes ในความคิดเห็นของพวกเขา

อย่างไรก็ตามวันนี้เว็บไซต์จำนวนมากจะมี IEBGENER "aliased" เป็น ICEGENER ICEGENER จะใช้ DFSORT ของ IBM (หรือคู่แข่ง SyncSort) ของ IBM เพื่อทำสำเนาเนื่องจากผลิตภัณฑ์ SORT ได้รับการปรับให้เหมาะสมสำหรับ IO มากกว่า IEBGENER

ฉันแค่ตัดชายกลางโดยใช้ SORT

หากคุณทำงานที่ไซต์ IBM Mainframe คุณรู้ว่ารูปแบบของการ์ด JOB ที่คุณควรใช้ การ์ด JOB ขั้นต่ำที่สุดเท่าที่ฉันได้แสดงโดยไม่มีความคิดเห็น ความคิดเห็นจะมีความสำคัญเนื่องจากคุณอาจต้องให้ข้อมูลทางบัญชีเป็นต้น ชื่องานน่าจะมีรูปแบบเฉพาะไซต์

บางเว็บไซต์แบนหรือป้องกันการใช้ INTRDR ระวัง.

บางไซต์อนุญาตให้มีหลายงานที่ใช้ชื่อเดียวกันทำงานได้ในเวลาเดียวกัน ระวัง.

แม้ว่าคุณจะเป็นโปรแกรมเมอร์ของระบบคุณไม่สามารถตั้งค่าคลาสดังกล่าวได้ แต่คุณควรมองหาคลาสที่อนุญาตให้มีผู้เริ่มต้นเพียงคนเดียว ด้วยกระบวนการนี้ค่อนข้างปลอดภัย แต่ต้องแน่ใจว่าคลาสใช้งานได้ตามที่อธิบายไว้ ทดสอบ. ไม่ได้อยู่กับงานนี้

หากคุณเป็นโปรแกรมเมอร์ของระบบคุณรู้ว่าจะไม่ทำอะไรนอกเหนือจากการชำระเงินของคุณ 'Nuff กล่าวว่า.

ด้วยหนึ่งงานที่มีชื่อเดียวกันที่ได้รับอนุญาตในเวลาเดียวกันและผู้เริ่มต้นคนเดียวนี่จะเป็นงานเริ่มต้น / เสร็จงานต่อไปงานเริ่มต้น / เสร็จงานถัดไปงานเริ่มต้น / เสร็จสิ้น - จนกว่าคุณจะกรอกสปูล งานนับพัน (หรือหมดจำนวนงาน) ดูคอนโซล JES สำหรับข้อความเตือน

โดยทั่วไปอย่าทำเช่นนี้ ถ้าคุณทำมันอย่าทำบนเครื่องผลิต

ด้วยการแปรงขึ้นเล็กน้อยฉันจะพิจารณาคำตอบอื่นสำหรับวิธีการทำบนระบบปฏิบัติการ IBM Mainframe อื่น z / VSE ... z / VSE ใช้ JCL z / OS ใช้ JCL พวกเขาแตกต่าง :-)


ความคิดดูดี แต่มันไม่ใช่คำตอบ แสดง JCL - JOB, EXEC และ DD - จากนั้นมันจะเป็นคำตอบ
ugoren

ยังไม่ได้ส่งงานมานานมากดังนั้นฉันไม่แน่ใจว่าจะทำอย่างไร หากชิ้นส่วนที่ขาดหายไปเป็นเพียงการปรับแต่งเฉพาะที่ให้เลือกตกลง แต่ถ้าคุณซ่อนสิ่งต่าง ๆ เพื่อป้องกันการละเมิดให้ทำการตัดสินใจ - โพสต์ของจริงหรือโพสต์อะไรเลย ป.ล. เราใช้IEBGENERแล้วในการคัดลอก
ugoren

@ugoren อัพเดตเพิ่มเติมรวมถึงคำอธิบายว่าทำไม IEBGENER ถึงไม่ถูกเลือกสำหรับงาน การลบข้อความแสดงความคิดเห็นในคำสั่ง JOB จะให้ JCL ที่จำเป็นสำหรับการรัน แต่ความเพียงพอของ JCL ขึ้นอยู่กับมาตรฐานของไซต์โลคัลไม่ว่าจะเป็นงานที่จะทำงานหรือสำหรับโปรแกรมเมอร์เพื่อหลีกเลี่ยงการถูกไล่ออก
Bill Woodger

4

Python (72 ไบต์)

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

อาจทำให้เล็กลงฉันเดา ก่อนอื่นโดย hardcoding ชื่อไฟล์ (แทนที่จะใช้__file__) แต่ที่นี่คุณสามารถใส่รหัสนี้ในไฟล์และเรียกใช้สิ่งที่ชื่อมันคือ :)


คุณอาจจะเปลี่ยนไป&& &
Hosch250

1
เมื่อใดที่อนุญาตให้ใช้ user2509848
Rhymoid

ดีที่คุณสามารถเริ่มต้นโดยการลบช่องว่าง ...
Ry-

6
เนื่องจากมันไม่ได้ติดแท็กcode-golfฉันจะเก็บรหัสดังนี้ :-)
Maxime Lorant

4

Windows Task Scheduler (.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 ++ / คำตอบ

โปรแกรมจะเริ่มและลงทะเบียนงานแบบใช้ครั้งเดียวด้วย Windows task scheduler เพื่อเริ่มตัวเองสูงสุด 60 วินาทีในภายหลัง (แผงควบคุม -> เครื่องมือการดูแลระบบ -> Task Scheduler เพื่อดูงานจะมีชื่อว่า "Restarter") โปรแกรมจะหยุดเป็นเวลา 5 วินาทีเพื่อให้คุณมีโอกาสฆ่ามันก่อนที่จะสร้างงาน

schtasks.exeทำให้การใช้อินเตอร์เฟซบรรทัดคำสั่ง Task Scheduler เลขคณิตในสคริปต์คือการคำนวณการชดเชยเวลาในขณะที่รักษาเวลาที่ถูกต้องและในรูปแบบ HH: MM

ข้อกำหนดในการท้าทาย:

  • เริ่มต้นตัวเองอีกครั้งเมื่อเสร็จสิ้น ใช่. งานถูกกำหนดไว้ก่อนที่โปรแกรมจะออก

  • ไม่มีมากกว่าหนึ่งอินสแตนซ์ของโปรแกรมที่ทำงานในเวลาเดียวกัน ใช่. ออกจากโปรแกรมอย่างสมบูรณ์และไม่ทำงานเป็นเวลา ~ 60 วินาที มันเริ่มจากตัวกำหนดตารางเวลา

  • คุณสามารถละเว้นอินสแตนซ์ใด ๆ ที่เริ่มต้นโดยผู้ใช้ด้วยตนเองในระหว่างรอบของคุณ ใช่เป็นผลข้างเคียงของการใช้ชื่อภารกิจคงที่

  • ตราบใดที่มันรับประกันว่ามันจะเริ่มขึ้นอีกครั้ง ใช่ระบุว่า Task Scheduler กำลังทำงานและ schtasks.exe มีอยู่ (ทั้งจริงในการกำหนดค่า Windows เริ่มต้น)

  • วิธีเดียวที่จะหยุดวงจรคือการฆ่ากระบวนการ ใช่กระบวนการสามารถถูกฆ่าได้ในช่วง 5 วินาทีขณะที่มันกำลังทำงาน โปรแกรมจะลบงานก่อนที่จะมีการหน่วงเวลา 5 วินาทีการฆ่ามันในเวลานี้จะไม่ปล่อยให้งานหลงทางอยู่ในตัวกำหนดตารางเวลา

  • โซลูชันของคุณไม่ควรเกี่ยวข้องกับการรีสตาร์ทสภาพแวดล้อม ใช่

หมายเหตุ: เนื่องจากอินเตอร์เฟสบรรทัดรับคำสั่งที่ จำกัด ต้องระบุเวลารีสตาร์ทเป็นนาทีและงานจะไม่รีสตาร์ทบนแล็ปท็อปโดยไม่ได้เสียบอะแดปเตอร์ AC (ขออภัย)


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 สำหรับการโกง
Johannes H.

1
ฮ่า แต่มันคือ "รับประกันว่ามันจะเริ่มอีกครั้ง" ถ้ามันไม่หยุด?
Jason C

นั่นเป็นเหตุผลที่ฉันพูดว่าฉันอาจจะผิดกฎ มันเป็นความงามทางปรัชญาของอินฟินิตี้ที่คุณสามารถสรุปได้ว่าอะไรจะเกิดขึ้นหลังจากนั้น เครื่องจักรทัวริงก็ทำเช่นนั้นเช่นกัน
microbian

1
-100 เพราะฉันไม่สนับสนุนให้คุณชนะการประกวดของคุณเองโดยเฉพาะอย่างยิ่งด้านเทคนิค แต่ +101 เพราะการรอให้รีสตาร์ทเป็นข้อแก้ตัวที่ดีที่สุดที่เคยมีมา
Jason C

คุณรู้แล้วwhile true; do sleep 1; donequilifies ใช่ไหม?
yo '22

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 ของคนจริง สุดท้ายของชนิด!
Jason C


1

ทุบตี

อีกนานกว่าจะเป็น แต่ฉันเหนื่อยและไม่สนใจ :)

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

คุณบอกว่ามันต้องรีสตาร์ทตัวเองเมื่อมันเสร็จคุณไม่ได้บอกว่ามันต้องทำซ้ำ ๆ ซ้ำ ๆ หรือไม่มีกำหนด นอกจากนี้คุณบอกว่าไม่ควรมีสองอินสแตนซ์ที่ทำงานพร้อมกัน ... มันจะไม่เกิดขึ้น ;)

มีหลายวิธีในการทำเช่นนี้ สิ่งที่ฉันชอบส่วนตัวคือจะทำอะไรบางอย่างเช่นส่งแพ็คเก็ตไปที่ไหนสักแห่งที่อยู่ห่างไกลจากนั้น (ผ่านวิธีการใด ๆ ก็ได้) ทำให้การตอบสนองนั้นกระตุ้นกระบวนการ


ในทางเทคนิคแล้วsleepกระบวนการจะรีสตาร์ทเมื่อเสร็จสิ้น
ace_HongKongIndependence

ถ้าโปรแกรมนั้นเป็นโปรแกรมที่รีสตาร์ทด้วยตนเองมันก็ส่อให้เห็นว่ามันต้องทำไปเรื่อย ๆ - ไม่เช่นนั้นมันจะรีสตาร์ทสิ่งอื่นที่ไม่ใช่ตัวมันเอง
Jason C

@ Jason 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

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

ไม่แน่ใจว่าสิ่งนี้เหมาะสมกับเกณฑ์ของคุณหรือไม่เพราะกระบวนการนี้ไม่ได้วางไข่ใหม่

โปรแกรมจะแสดงกล่องข้อความจัดสรรหน่วยความจำบางส่วนคัดลอกส่วนรหัสของตัวเองลงในหน่วยความจำที่จัดสรรแล้วข้ามไปยังตำแหน่งนั้นเพื่อเริ่มวัฏจักร ควรรันจนกว่า 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'

คอมไพล์ด้วย fasm


4
เนื่องจากเป็นส่วนหนึ่งของโปรแกรมของคุณที่จะเรียกใช้รหัสที่ถูกคัดลอกใหม่ดังนั้นในทางเทคนิคแล้วโปรแกรมของคุณไม่เคยเสร็จสมบูรณ์เลย
microbian

6
จากมุมมองระดับต่ำสามารถพูดได้เหมือนกันว่าโปรแกรมทั้งหมดที่นี่ :-)
Brian Knoblauch

@BrianKnoblauch ฉันไม่เห็นด้วย คำตอบที่น่าสนใจที่สุดที่นี่ดูเหมือนจะแก้ไขสภาพแวดล้อมของระบบเพื่อให้สำเนาใหม่ของกระบวนการเริ่มขึ้นหลังจากที่ถูกฆ่าครั้งแรก ตัวอย่างเช่นฉันคิดว่าการสร้างงาน chron เพื่อเรียกใช้กระบวนการในอนาคตจะเป็นวิธีที่ดีในการปล่อยให้กระบวนการนั้นตายอย่างสมบูรณ์จากนั้นเริ่มต้นใหม่
Kevin - Reinstate Monica

2
@BrianKnoblauch ไม่จริง กระบวนการคือการสร้างระบบปฏิบัติการ (ซึ่งในทุกวันนี้ - เช่นเดียวกับที่มีโหมดป้องกันใน 286 ในปี 1982 - ได้รับการสนับสนุนโดยฮาร์ดแวร์ผ่านพื้นที่ที่อยู่เสมือนและหน่วยความจำที่ได้รับการป้องกัน) เมื่อมันสิ้นสุดข้อมูลทั้งหมดจะหายไป แม้ว่าจะไม่ได้ระบุไว้อย่างชัดเจนในการท้าทาย แต่ฉันใช้จิตวิญญาณของความท้าทายเพื่อหมายความว่า "การเริ่มใหม่" หมายความว่ามีการกำหนด ID กระบวนการใหม่
Jason C

ดีฉันจะให้ +1 ถ้าคุณจัดการเพื่อเพิ่มหน่วยความจำระหว่างทาง (โปรด ping ฉันโดย@ทันทีที่คุณจัดการเนื่องจากฉันมีแนวโน้มที่จะไม่จับตาดูมัน)
โย่

0

Linux พุ่งพรวด init

ด้วยการอ่านคำถามที่เข้มงวดที่สุดฉันคิดว่ามันเป็นไปไม่ได้ โดยพื้นฐานแล้วมันคือการขอให้โปรแกรมเริ่มต้นเองโดยไม่มีความช่วยเหลือจากโปรแกรมอื่นที่กำลังทำงานอยู่

มีอยู่บ้าง atและchronชั่นตอบ แต่มีการอ่านที่เข้มงวดatdและanacronเป็นโปรแกรมเสริมที่มีการทำงานตลอดเวลาเพื่อให้พวกเขาอาจถูกตัดสิทธิ์

วิธีการที่เกี่ยวข้อง initแต่ระดับที่ต่ำกว่าเล็กน้อยคือการใช้ลินุกซ์ ในฐานะ root ให้เพิ่มไฟล์. conf นี้ไปที่/etc/init/:

คำอธิบาย "ตลอดไป"

เริ่มที่ runlevel [2345]
หยุดที่ runlevel [! 2345]

respawn

exec sleep 10

จากนั้นให้initอ่านไฟล์. config อีกครั้ง:

sudo telinit 5

สิ่งนี้จะเริ่มsleepกระบวนการที่จะมีชีวิตอยู่เป็นเวลา 10 วินาทีจากนั้นออก initจะเกิดใหม่อีกครั้งsleepอีกครั้งเมื่อตรวจพบสิ่งที่เคยทำไปแล้ว

ของหลักสูตรนี้ยังคงใช้initเป็นโปรแกรมเสริม คุณสามารถยืนยันว่าinitเป็นส่วนขยายตรรกะของเคอร์เนลและจะเสมอสามารถใช้ได้ในลินุกซ์ใด ๆ

หากสิ่งนี้ไม่เป็นที่ยอมรับฉันคาดเดาว่าสิ่งที่ต้องทำในระดับต่ำกว่าถัดไปคือการสร้างเคอร์เนลโมดูลที่ตอบสนองกระบวนการผู้ใช้ (ไม่แน่ใจว่าง่ายแค่ไหน) ที่นี่สามารถโต้เถียงได้ว่าเคอร์เนลไม่ใช่กระบวนการดังนั้นจึงไม่ใช่โปรแกรม (เพิ่มเติม) ในทางกลับกันเคอร์เนลเป็นโปรแกรมในสิทธิของตนเองจากจุดของ CPU


-1

TI-BASIC: 5 ตัวอักษร

เรียกมันว่า prgmA

:prgmA

ฉันสามารถนับได้ 6 ตัวอักษร มีอะไรพิเศษเกี่ยวกับการนับขนาดโปรแกรม TI-BASIC หรือไม่
ace_HongKongIndependence

นี่:เป็นเพียงสัญลักษณ์เริ่มต้นของเส้นเมื่อใดก็ตามที่คุณเขียนโปรแกรมใน TI-Basic ไม่ใช่สิ่งที่คุณพิมพ์ แต่มีอยู่ในเครื่องมือแก้ไข
scrblnrd3

ฉันเห็นว่าขอบคุณสำหรับข้อมูล
ace_HongKongIndependence

นั่นไม่ได้เป็นการเรียกซ้ำหรือไม่? ลองเพิ่มAและใช้ค่าเป็นกรณีพื้นฐานคุณจะเห็นว่ามันก้าวออกมาในที่สุด
ζ--

ทีนี้ตัวแปรทั้งหมดเป็นรูปกลมในรูป ti-basic ดังนั้นฉันไม่แน่ใจ อาจเป็น
scrblnrd3
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.