Un programme qui se termine mais ne se termine jamais [fermé]

35

Ecrivez un programme qui se recommence à la fin.

Il ne devrait pas y avoir plus d'une instance du programme en cours d'exécution en même temps. Pas même pour le moindre moment.

Vous pouvez ignorer toute instance démarrée manuellement par l'utilisateur au cours de votre cycle. Mais votre code ne devrait pas le faire dans votre cycle de redémarrage.

Le programme peut démarrer après n’importe quelle durée, à condition qu’il soit garanti qu’il redémarre.

Le seul moyen d'arrêter le cycle est de tuer le processus.

Votre solution ne devrait pas impliquer le redémarrage de l'environnement (dans lequel le programme est en cours d'exécution, inclut le système d'exploitation, la machine, la machine virtuelle, le shell, etc.). Seul votre programme est autorisé à redémarrer.

microbien
la source
11
N'est-ce pas ce que execfait Linux?
Mniip
11
Je suis un peu paresseux pour l'écrire maintenant, mais ma soumission serait (pour Windows): "Modifiez le registre pour que mon programme démarre au démarrage. Exécutez shutdown -r -t 0 -f".
Cruncher
3
Tuer le processus ne tuera pas votre cycle cependant.
Microbian
19
Je viens de me rendre compte que: si je veux écrire un virus sans savoir comment, je pourrais 1) accéder à StackOverflow, demander comment. Obtenez la haine de tout le monde et probablement la question sera fermée. Ou 2) Allez au code golf, demandez aux autres comment ils le feraient. Choisissez parmi une poignée de réponses créatives, et la question est si populaire qu'elle figure sur la liste "dynamique" du réseau. Mua ha ha ha ha.
rumtscho
5
@rumtscho Vous savez, c'est une bonne stratégie générale. Ok les gars, pour mon prochain défi, voyons qui peut écrire le plus petit firmware pour le prototype de périphérique assis sur mon bureau qui répond à toutes les exigences du document lié. Pour pimenter, cela doit être fait lundi matin à 8 heures. Aller!
Jason C

Réponses:

50

Script Bash, 3 caractères (Le plus court, peut-être le plus élégant, bien que controversé)

$0&

Il place simplement une nouvelle instance de lui-même en arrière-plan (nouveau processus), puis se ferme. La nouvelle instance restera probablement dans la file d'attente du planificateur jusqu'à ce que l'instance précédente soit terminée.

Avertissement - cela est difficile kill, car le PID change continuellement. Renommer temporairement le fichier de script est probablement le moyen le plus simple de rompre le cycle.

Un système monocœur est supposé. Bien sûr, cela n’est pas réaliste avec Linux sur du matériel nu-metal moderne, mais il est facilement configurable lorsqu’il est exécuté sur une VM. Nous pourrions probablement réaliser une astuce similaire en utilisant taskset, mais cela réduirait l'impact de la solution à 3 caractères.

Cette réponse déroge un peu aux règles dans le sens où elle applique un sens spécifique de "courir". Il y aura des moments où le nouveau processus aura été fork()modifié et où l'ancien processus sera toujours actif - c'est-à-dire qu'il sera peut-être possible d'observer plus d'un PID. Toutefois, le nouveau processus sera placé dans la file d'attente d'exécution du planificateur Linux pour attendre les cycles du processeur, tandis que le processus existant continuera à s'exécuter. À ce stade, tout ce qui doit être fait par le processus existant bashs’impose à lui-même exit(). Cela prend un temps fini, même si je suis assez confiant que cela sera fait bien avant que le quantum actuel de timelice / scheduler soit terminé. Les preuves à l'appui sont le fait que bashdémarre et s'arrête en 2ms sur ma VM:

$ time bash -c:

réel 0m0.002s
utilisateur 0m0.000s
sys 0m0.000s
$ 

Les autres éléments de preuve à l'appui du fait que le nouveau processus ne s'exécute pas tant que le processus précédent n'est pas terminé sont visibles dans l' straceoutput:

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

Dans la sortie, nous voyons que le processus d'origine a le PID 6929. Nous pouvons voir l' fork()appel (en fait clone()), qui renvoie un nouveau PID de 6930. À ce stade, il existe 2 PID, mais seul le 6929 est en cours d'exécution:

6929 12: 11: 01.031398 clone (child_stack = 0, flags = 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 read (255, "", 4) = 0
6929 12: 11: 01.031907 exit_group (0) =?
6930 12: 11: 01.032016 close (255) = 0
6930 12: 11: 01.032052 rt_sigprocmask (SIG_SETMASK, [], NULL, 8) = 0

straceSortie complète ici.

Nous pouvons voir que le 6930 n’émet aucun appel système jusqu’à ce que le 6929 soit complètement terminé. Il est raisonnable de supposer que cela signifie que 6930 ne fonctionne pas du tout jusqu'à ce que 6929 soit terminé. L' perfutilitaire serait le moyen ultime de le prouver.

Trauma numérique
la source
21
"redémarre ..., puis quitte", donc plus d'une instance s'exécute en même temps?
Microbian
4
"... sur single core" - oui, je suppose aussi. Sur plusieurs noyaux, vous pourrez probablement en voir beaucoup.
blabla999
3
Si cela a été marqué code-golf, alors cela va certainement gagner! +1
John Odom
3
@ DigitalTrauma Vous faites des hypothèses énormes sur le temps qu'il faut à bash pour se fermer. top ne vous dit rien - il ne se met à jour qu'une fois toutes les quelques dizaines de secondes, mais vous créez de nombreux processus par seconde.
David Richerby
2
@DavidRicherby - vous avez absolument raison - topn'est pas le bon outil à utiliser ici. Cependant, je vois que cela time bash -c :ne prend que 2 ms sur ma machine virtuelle Ubuntu, donc je ne pense pas qu’il soit déraisonnable de s’attendre bashà terminer son arrêt avant que son quantum de planification ne soit terminé.
Trauma numérique
26

Solution 1

PHP, 32 caractères

Il envoie l'en-tête puis il s'arrête. Après 3 secondes, la page est rechargée.

fichier a.php

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

Cela peut être arrêté en mettant fin à l'exécution de la page avant l'envoi des en-têtes ou simplement en tuant le navigateur.


Solution 2

PHP, 2 pages

Considérons les deux fichiers deux programmes différents. Les deux fichiers sont dans le même dossier.

fichier a.php

header("Location:b.php");

fichier b.php

header("Location:a.php");

Terminer une des pages avant que les en-têtes ne soient envoyés met fin au programme (tuer le navigateur fonctionne également).

Voici le même programme dans

ASP.NET

fichier a.aspx

Response.Redirect("b.aspx")

fichier b.aspx

Response.Redirect("a.aspx")
Vereos
la source
1
C'est une belle solution. J'espère que d'autres apporteront des réponses différentes de celles-ci. C'est pourquoi je l'ai gardé comme un concours de popularité.
Microbian
Que votre réponse de rechargement de 3 secondes soit valide ou non, je le laisse aux experts php. Je pense que cela pourrait être valable, car c'est le navigateur qui n'attend pas votre php (je ne suis pas un expert).
Microbian
1
Bien que, techniquement, PHP soit exécuté en tant que module d’un serveur Web et que votre serveur Web n’ait pas redémarré, je pense que cela est valable si vous considérez un fichier .php comme un script et si le script est exécuté plusieurs fois.
TwiNight le
@TwiNight Merci pour les commentaires, j'apprécie :)
Vereos
2
Pour votre deuxième solution, le navigateur ne détecte-t-il pas une boucle de redirection et s’arrête-t-il seul? thedan1984.com/wp-content/uploads/2012/02/...
Ajedi32
19

sh

echo $PWD/$0 | at tomorrow

Cela fonctionnera sur n’importe quel système conforme à Posix.

Pour le tuer, supprimez le fichier ou utilisez atrm.

ecatmur
la source
17

frapper

exec "$0"

execremplace le shell sans créer de nouveau processus. Cela garantit qu'il ne peut y avoir une deuxième instance.

Dennis
la source
1
Mieux vaut le mettre dedans ~/.bash_profile!
Yegle
@yegle: $0est -bashquand .bash_profileest source, ce qui entraînerait une erreur de syntaxe.
Dennis
Oups, tu as raison.
Yegle
exec ${0##-}dans les ~/.bash_profiletravaux :-)
yegle
14

Planificateur de tâches Windows (natif)

C ++. Un cauchemar de la programmation COM. Répond à toutes les exigences du défi.

#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);

}

Compilez avec MSVC (ou MinGW GCC si vous avez toutes les dépendances).

Le programme va démarrer et enregistrer une tâche unique avec le planificateur de tâches Windows pour démarrer lui-même 5 secondes plus tard (Panneau de configuration -> Outils d'administration -> Planificateur de tâches à afficher, la tâche est nommée "Restarter"). Le programme s'interrompt pendant 5 secondes pour vous donner une chance de le tuer avant qu'il ne crée la tâche.

Exigences du défi:

  • Se remet en marche quand fini. Oui. La tâche est planifiée juste avant la sortie du programme.

  • Pas plus d'une instance du programme en cours d'exécution en même temps. Oui. Le programme se termine complètement et ne s'exécute pas pendant 5 secondes. Il est lancé par le planificateur.

  • Vous pouvez ignorer toute instance démarrée manuellement par l'utilisateur au cours de votre cycle. Oui, comme effet secondaire de l’utilisation d’un nom de tâche constant.

  • Tant qu'il est garanti que cela recommence. Oui, à condition que le planificateur de tâches soit en cours d'exécution (il s'agit d'une configuration Windows standard).

  • Le seul moyen d'arrêter le cycle est de tuer le processus. Oui, le processus peut être tué pendant la fenêtre de 5 secondes pendant son exécution. Le programme supprime la tâche avant le délai de 5 secondes. La tuer à ce moment-là ne laissera pas une tâche parasite dans le planificateur.

  • Votre solution ne devrait pas impliquer le redémarrage de l'environnement . Oui.

À propos, si quelqu'un se demandait pourquoi les applications Windows étaient si instables (avant l'avènement de .NET et C #), c'est l'une des raisons. La quantité de gestion d'erreur requise (si je l'avais incluse), la gestion des ressources et la verbosité créent des situations très sujettes aux erreurs si un programmeur est même le plus peu paresseux (le code ci-dessus est extrêmement paresseux).

Une alternative beaucoup plus facile et plus courte consiste à appeler schtasks.exe. J'ai également soumis une version avec cela dans un script .BAT .

Jason C
la source
13

BBC BASIC - un hommage à Snow Patrol

Emulator sur bbcbasic.co.uk

Celui-ci est un peu différent. Il imprime un couplet de la chanson "Run" et joue un arpège d'accords pour que vous puissiez chanter. Cela a été inspiré par le fait que la commande à exécuter (et donc la dernière ligne du programme) est bien sûr RUN.

Toutes les variables sont effacées au début du programme, il faut donc que la couleur de l'écran laissée par l'itération précédente soit choisie pour décider quel verset imprimer ensuite.

    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

SORTIE (montage de 4 captures d'écran différentes)

enter image description here

Level River St
la source
+1 pour la solution couleur comme alternative "mémoire partagée".
Johannes H.
11

HTML / JavaScript:

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

Le code déclenche la destruction de la page sur laquelle il s'exécute, puis la recréation d'une autre instance lorsque le navigateur charge à nouveau la page.

Autant que je sache, le seul moyen de sortir est de tuer l'onglet dans lequel la page est en cours d'exécution.

EDIT: selon la demande courante, un code HTML5 valide:

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

la source
@JasonC Je ne suis pas d'accord. Je pense que les pages raisonnables devraient être conformes aux spécifications, mais les concours de popularité sont tout à fait supposés être raisonnables, n'est-ce pas? : D donc +1, j'aime vraiment celui-ci.
Yo '22
10

C

Ce programme agit comme beaucoup de malware. Juste avant de se fermer, il crée un script shell dans le répertoire / tmp. Il demande de démarrer le script shell, ce qui permet au programme original de se fermer et d’annuler le PID original. Après une brève période (2 secondes), le script shell démarre un nouveau processus avec le programme. Par souci de brièveté, l'emplacement du programme est câblé en tant que '/ 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]);
}

Il n'y a jamais qu'un processus "Neverend" en cours d'exécution à la fois. Chaque nouveau processus reçoit un nouveau PID. Le moyen le plus simple de le supprimer consiste à supprimer le fichier exécutable. Si vous voulez rendre le processus plus malin, vous pouvez copier l'exécutable et le script pour vous assurer qu'il y a plusieurs copies sur le programme sur le disque à tout moment.

Kevin
la source
1
Je m'attends à voir plus de réponses innovantes. Voir les commentaires pour la question sur les «programmes de suppléments». Pour moi, un programme de supplément n'est qu'un élément de votre programme qui traîne en longueur.
microbien
4
Forking signifie que deux instances du processus s'exécutent en même temps, même si leurs tâches sont différentes.
Barry Fruitman
@ BarryFruitman est facile à éviter, cependant, en utilisant vraiment deux exécutables différents. C'est valable alors, mais beaucoup moins élégant.
Johannes H.
Je suppose que vous pourriez utiliser system()si les règles ne comptent pas un fork + exec /bin/shcomme un programme supplémentaire.
Jason C
10

Perl

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

Le script émet une commande système pour se tuer et dirige le résultat vers une autre instance d'elle-même. L'interprète Perl est utilisé pour tuer, pour des raisons de plate-forme croisée.

Arrêtez la folie en supprimant le script.

primo
la source
7

Atari 8 bits de base

1L.:R.

Tokenizes to:

1 LIST : RUN

En interne, il nettoie les structures internes, essentiellement en supprimant le programme, avant de le réexécuter à partir de la liste.

Ceci est fondamentalement différent de:

1L.:G.1

Quel tokenize to:

1 LIST : GOTO 1

Ceci est une boucle infinie de base. Lorsque vous les exécutez, vous voyez la différence de vitesse (la première est plus lente).


la source
Je ne comprends pas très bien pourquoi une "liste" au cours de l'exécution du programme efface toutes les structures internes. Je pense que l’Atari a un tampon clavier, donc on pourrait lister le programme, bourrer les touches pour l’exécuter, et faire un "nouveau" avec le curseur positionné pour le "retaper".
Supercat
@supercat - LIST non, RUN non plus.
Selon cette logique, on pourrait omettre la "LISTE". Par contre, si le programme bourrait la mémoire tampon du clavier, avec quelques retours à la main, mettez "NEW" suivi du programme et "RUN" aux bons endroits de l'écran, relocalisez le curseur et sortez, il s'effacerait réellement. et se retaper automatiquement.
Supercat
@supercat - sans le LIST, vous ne le verriez pas fonctionner. J'ai choisi LISTparce qu'il a l'entrée la plus courte L.. J'aime l'idée de mettre cela dans un tampon de clavier, c'est certainement assez court!
Est-ce que je me souviens bien que l'Atari, comme les machines Commodore, lit le texte à l'écran lorsque vous appuyez Return? Quelle est la taille de la mémoire tampon du clavier? Sur le VIC-20 et le C64, il s’agit de dix octets. Un programme qui fait assez de pokes pour charger la mémoire tampon du clavier ne rentrerait probablement pas dans la mémoire tampon du clavier, mais j’ai écrit des programmes qui se modifieraient eux-mêmes en imprimant les modifications à l’écran suivies de RUNet en tapant quelques Returntouches. De telles choses étaient particulièrement utiles sur le 64 car il n'avait pas la INcommande [IIRC] d' Atari pour fusionner des lignes dans un programme.
Supercat
5

Sur un mainframe IBM exécutant z / OS, vous exécutez un utilitaire qui copie un jeu de données (fichier) dans un autre jeu de données (fichier). L'entrée est la source du JCL (Job Control Language) que vous avez soumis afin de l'exécuter. La sortie est le lecteur interne (INTRDR). Vous devrez également vous assurer que votre système n'autorise pas l'exécution de plusieurs noms de travail identiques. Il est bon d'utiliser une classe de travail qui n'a qu'un seul initiateur (endroit où un travail peut être exécuté par lots).

Il n'y a pas de PID impliqué (dans z / OS), l'échec est donc impossible.

Vous arrêtez le processus en drainant et / ou en rinçant. Si quelque chose ne va pas, en vidant et / ou en rinçant, en jurant, en donnant un coup de pied, en essayant un démarrage à chaud et finalement par un démarrage à froid ou en appuyant sur le gros bouton rouge (et en tirant sur le programmateur).

J'ai peut-être exagéré en cours de route, mais n'essayez pas cela au travail ...

Exemple utilisant SORT. Les détails sur la carte de travail dépendent beaucoup du site. La politique du site peut interdire ou empêcher l’utilisation d’INTRDR. Une classe spécifique peut être nécessaire pour utiliser INTRDR. Si la politique de votre site interdit son utilisation , ne l'utilisez pas sauf si vous souhaitez vous promener avec vos biens personnels dans une boîte en carton.

Bien que l’INTRDR présente de bonnes utilisations, ne l’utilisez pas à cette fin . Vous n'aurez même pas la chance d'obtenir votre boîte.

//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) 

D'autres utilitaires sont disponibles. Un programme rapide serait aussi facile à faire: il suffit de lire un fichier, d’écrire un fichier.

Si vous voulez un exemple d'erreur, essayez: http://ibmmainframes.com/viewtopic.php?p=282414#282414

La manière traditionnelle de copier un jeu de données consiste à utiliser l'utilitaire IBM IEBGENER, comme le fait remarquer ugoren dans ses commentaires.

Cependant, ces jours-ci, de nombreux sites auront IEBGENER "aliasé" par ICEGENER. Si cela est possible, ICEGENER utilisera DFSORT d’IBM (ou son rival SyncSort) pour effectuer une copie, car les produits SORT sont beaucoup plus optimisés pour IO que IEBGENER.

Je coupe juste l'intermédiaire en utilisant SORT.

Si vous travaillez sur un site IBM Mainframe, vous connaissez le format de la carte de travail que vous devez utiliser. La carte JOB minimale est comme je l’ai montré, sans le commentaire. Le commentaire sera important, car vous pouvez être supposé fournir des informations comptables, par exemple. Le nom du travail aura probablement un format spécifique au site.

Certains sites interdisent ou empêchent l’utilisation de INTRDR. Savoir.

Certains sites permettent l'exécution simultanée de plusieurs tâches du même nom. Savoir.

Bien que, sauf si vous êtes programmeur système, vous ne pouvez pas configurer une telle classe, vous devez rechercher une classe qui n'autorise qu'un seul initiateur. Avec cela, le processus est assez sûr - mais soyez absolument sûr que la classe fonctionne comme décrit. Tester. Pas avec ce travail.

Si vous êtes un programmeur système, vous savez qu'il ne faut rien faire en dehors de vos attributions. 'Nuff a dit.

Avec un travail portant le même nom autorisé en même temps et un seul initiateur, il s'agira d'un flux constant de début / fin de travail, début / fin du travail suivant, jusqu'à ce que vous remplissiez le spool (autre mauvaise chose à faire) avec la sortie de des milliers d'emplois (ou à court de nombre d'emplois). Surveillez une console JES pour les messages d'avertissement.

En gros, ne faites pas ça. Si vous le faites, ne le faites pas sur une machine de production.

Après un peu de relooking, je considérerai une autre réponse pour savoir comment le faire sur un autre système d'exploitation IBM Mainframe, z / VSE ... z / VSE utilise JCL. z / OS utilise JCL. Ils sont différents :-)

Bill Woodger
la source
L'idée est bonne, mais ce n'est pas une réponse. Montrez-nous le JCL - JOB, EXEC et DD - alors ce sera une réponse.
Ugoren
Je n'ai pas soumis de travail depuis très longtemps, alors je ne sais pas quoi en faire. Si les pièces manquantes ne sont que des personnalisations locales, cliquez sur OK. Mais si vous cachez des éléments pour empêcher un abus, alors décidez-vous - affichez le contenu réel ou ne publiez rien. PS Nous avons utilisé IEBGENERà l'époque pour simplement copier.
Ugoren
@ugoren Nouvelle mise à jour, y compris une explication de la raison pour laquelle IEBGENER n'a pas été sélectionné pour la tâche. La suppression du commentaire sur l’instruction JOB fournit le JCL nécessaire à son exécution, mais sa suffisance dépend des normes du site local, que le travail fonctionne ou que le programmeur évite d’être licencié.
Bill Woodger
4

Python (72 octets)

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

Pourrait être plus petit je suppose. Tout d'abord, en codant en dur le nom du fichier (au lieu d'utiliser __file__). Mais ici, vous pouvez mettre ce code dans un fichier et l'exécuter, quel que soit son nom :)

Maxime Lorant
la source
Vous pouvez probablement changer &&pour &.
Hosch250
1
Depuis quand est-ce autorisé, user2509848?
Rhymoid
Eh bien, vous pourriez commencer par supprimer les espaces blancs…
Ry-
6
Comme ce n'est pas tagué code-golf , je vais garder le code comme ceci :-)
Maxime Lorant
4

Planificateur de tâches Windows (.BAT)

Script batch Windows. Répond à toutes les exigences du défi.

Pour autant que je sache, il s’agit de la seule solution Windows à ce jour qui répond à toutes les exigences et ne présente aucune dépendance non standard (mon autre solution est similaire mais nécessite une compilation).

@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

Le programme se comporte de la même manière que ma réponse C ++ / COM .

Le programme démarrera et enregistrera une tâche unique avec le planificateur de tâches Windows pour se lancer jusqu'à 60 secondes plus tard (Panneau de configuration -> Outils d'administration -> Planificateur de tâches à afficher, la tâche est nommée "Restarter"). Le programme s'interrompt pendant 5 secondes pour vous donner une chance de le tuer avant qu'il ne crée la tâche.

Utilise l'interface du planificateur de tâches en ligne de commande schtasks.exe. Dans le script, l'arithmétique consiste à calculer des décalages horaires tout en conservant l'heure valide et au format HH: MM.

Exigences du défi:

  • Se remet en marche quand fini. Oui. La tâche est planifiée juste avant la sortie du programme.

  • Pas plus d'une instance du programme en cours d'exécution en même temps. Oui. Le programme se termine complètement et ne s'exécute pas pendant environ 60 secondes. Il est lancé par le planificateur.

  • Vous pouvez ignorer toute instance démarrée manuellement par l'utilisateur au cours de votre cycle. Oui, comme effet secondaire de l’utilisation d’un nom de tâche constant.

  • Tant qu'il est garanti que cela recommence. Oui, à condition que le planificateur de tâches soit en cours d'exécution et que schtasks.exe soit présent (les deux sont vrais dans les configurations Windows par défaut).

  • Le seul moyen d'arrêter le cycle est de tuer le processus. Oui, le processus peut être tué pendant la fenêtre de 5 secondes pendant son exécution. Le programme supprime la tâche avant le délai de 5 secondes. La tuer à ce moment-là ne laissera pas une tâche parasite dans le planificateur.

  • Votre solution ne devrait pas impliquer le redémarrage de l'environnement . Oui.

Remarque: en raison d'une interface de ligne de commande limitée, le temps de redémarrage doit être spécifié en minutes et la tâche ne redémarrera pas sur les ordinateurs portables sans l'adaptateur secteur branché (désolé).

Jason C
la source
3

Shell Unix

Je n'ai pas encore vu beaucoup de solutions qui reposent sur un programme indépendant pour le redémarrer. Mais c’est exactement pour cela que cet at(1)utilitaire a été conçu:

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

Il est difficile de suivre le programme en cours, car il ne s'exécute qu'une fois par minute et se termine si rapidement. Heureusement, l' atq(1)utilitaire vous montrera qu'il continue toujours:

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

Et atrm(1)vous permettra de briser le cycle:

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

Vous pouvez remplacer 1 minutepar 1 hour, ou 1 week. Ou donnez-lui 1461 daysd'avoir un programme qui fonctionne une fois tous les 4 ans.

boite à pain
la source
2

PowerShell

J'abuse (et éventuellement enfreint) ma propre règle.

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

Cela prend une quantité infinie de temps pour se relancer.
Il peut être tué en éliminant le processus hôte.

Attendez et voyez;)

microbien
la source
5
+1 pour la créativité, mais -1 pour la triche.
Johannes H.
1
Ha, mais est-il "garanti que ça recommence" s'il n'arrête jamais?
Jason C
C'est pourquoi j'ai dit que je vais probablement enfreindre la règle. C'est la beauté philosophique de l'infini que vous pouvez supposer que tout peut arriver après cela. La machine de Turing fonctionne aussi de cette façon.
Microbian
1
-100 parce que je ne vous aide pas à gagner votre propre concours, surtout pour des raisons techniques, mais +101 car attendre qu'il redémarre est la meilleure excuse pour la procrastination.
Jason C
Eh bien, vous savez, alors, while true; do sleep 1; donequalifie, n'est-ce pas?
Yo '22
2

Frapper

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

Enregistrez-le sous le nom repeat.sh dans le répertoire / et donnez-lui l'autorisation d'exécution. Il peut être tué en supprimant le fichier

Cela fonctionne en mettant une entrée dans la crontab pour l'exécuter 1 minute plus tard.

g.rocket
la source
2

Visual Base 6 :)

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

Pour exécuter, créer un nouveau projet, ajouter un module avec ce code, définir l'objet de démarrage sur "Sub Main", compiler, puis exécuter le fichier exécutable.


Version plus lisible:

Sub Main()
    Call Shell("cmd ping 1.1.1.1 -n 1 -w 3000 > nul && """ & App.Path & "\" & App.EXEName & """")
End Sub
Brosse à dents
la source
VB6 est le VB d'un vrai homme. Le dernier du genre!
Jason C
1

HTML / JAVASCRIPT

FICHIER HTML a.html

<script>window.location = "a.html"</script>
Clyde Lobo
la source
1

Frapper

Plus long que ça doit l'être, mais je suis fatigué et je m'en fiche :)

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

Vous avez dit qu'il doit se redémarrer à la fin, vous n'avez pas précisé qu'il devait le faire à répétition ou indéfiniment. En outre, vous avez dit qu'il ne devrait jamais y avoir deux instances en cours d'exécution à la fois ... jamais. ;)

Il y a beaucoup de façons de le faire. Mon choix personnel serait de faire quelque chose comme envoyer un paquet quelque part, et ensuite (via n'importe quel moyen), de faire en sorte que la réponse déclenche le processus.

Ian Wizard
la source
Techniquement, le sleepprocessus redémarre à la fin.
pastebin.com slash 0mr8spkT
Si le programme est un programme qui le redémarre tout seul , il est alors implicite qu'il doit le faire indéfiniment - sinon, il redémarre quelque chose d'autre qui n'est pas lui-même.
Jason C
@Jason C: Sans devenir trop philosophique, dans la mesure du possible, il redémarre tout seul. On pourrait débattre de la façon complexe , il doit être de redémarrer vraiment ce moi , mais je pense que c'est bien au - delà ce que l'auteur voulait dire. Cependant, si vous voulez qu'il redémarre vraiment, il est probable que quelque chose utilise goto, JMP ou toute autre construction proposée par votre langage, pour revenir au début. Sinon, il s'agit simplement d'exécuter quelque chose qui se ressemble distinctement. Mais alors, quelqu'un s'inquiètera probablement du fait que cela ne redémarre pas vraiment. Alors je m'égare.
Ian Wizard
1

Android: une alarme va redémarrer l'activité après 1 seconde

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();
}

}
fil67
la source
1

Environnement 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");
    }
}

Vous devez avoir OpenMPI ou une autre implémentation MPI installée. Compiler avec

mpicc -o mpifork mpifork.c

Maintenant que j'y pense, il n'y a aucune raison pour que vous utilisiez mpicc - gcc ou le compilateur qui fonctionne. Vous devez juste avoir mpirun.

gcc -o mpifork mpifork.c

Pour l'exécuter, vous devez probablement inclure le nom du chemin complet et inclure une liste d'hôtes. Par exemple, j'ai ajouté des entrées dans / etc / hosts qui pointaient toutes vers localhost et je les ai exécutées comme suit:

/home/phil/mpifork localhost localhost1 localhost2 localhost3 localhost4

L'exécutable doit se trouver dans le même répertoire sur n'importe quel ordinateur sur lequel vous souhaitez l'exécuter.


Cela prend essentiellement une liste d'hôtes fournie sur la ligne de commande, sélectionne l'un des hôtes et lance l'exécutable sur l'hôte cible avec les mêmes arguments. Si tout se passe bien, mpirun s'appellera encore et encore sur différentes machines (ou sur la même machine si vous ne fournissez que 'localhost'. L'exécutable lui-même (mpifork) se termine. Après avoir appelé execvp, il ne s'exécute plus sur la première machine.

Si vous vouliez être diabolique, vous pourriez plutôt lancer ce lancement sur chaque machine, en incluant la liste complète des hôtes fournie sur la ligne de commande args. Cela créerait une copie de lui-même sur chaque machine, encore et encore - un forkbomb en grappe.

Cependant, sous cette forme, je suis à peu près sûr que cela satisfait aux règles.

Millinon
la source
1

JavaScript

Sans "aller sur le réseau" quand cela n'est pas nécessaire :-) La planification de boucle d'événement de JavaScript nous permet d'écrire des programmes qui répondent aux exigences données très facilement:

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

Ceci "redémarre" la programfonction à un rythme de 10 fois par seconde. De par la nature de JavaScript, il est garanti qu'une seule tâche sera exécutée en même temps, et cela ne "redémarre pas l'environnement" comme dans "recharger la page".

Bergi
la source
0

Assemblée x86

Je ne suis pas tout à fait sûr que cela corresponde à vos critères car cela ne déclenche pas un nouveau processus, mais le voici quand même.

Le programme affichera une boîte de message, allouera de la mémoire, copiera sa propre section de code dans la mémoire allouée, puis passera à cet emplacement en commençant le cycle. Il devrait fonctionner jusqu'à ce que malloc échoue.

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'

Compilé avec fasm.

oscar
la source
4
Puisqu'il fait partie de votre programme d'appeler le code nouvellement copié, techniquement votre programme ne s'est jamais terminé du tout.
Microbian
6
D'un point de vue de bas niveau, on pourrait en dire autant de tous les programmes ici. :-)
Brian Knoblauch le
@BrianKnoblauch Je ne suis pas d'accord. Les réponses les plus intéressantes semblent modifier l’environnement système de sorte qu’une nouvelle copie du processus soit démarrée quelque temps après la suppression de la première. Par exemple, je penserais que créer un travail chron pour exécuter le processus à l'avenir serait un bon moyen de laisser le processus complètement mourir, puis d'être redémarré.
Kevin - Réintégrer Monica
2
@BrianKnoblauch Pas vraiment. Un processus est une construction de système d'exploitation (qui, de nos jours, comme depuis l'avènement du mode protégé dans le 286 en 1982, est également sauvegardé matériellement via des espaces d'adressage virtuels et une mémoire protégée). Quand cela se termine, toute cette information disparaît. Bien que cela n’ait pas été explicitement indiqué dans le défi, j’entends bien par esprit de défi que "redémarrer" implique l’attribution d’un nouvel identifiant de processus.
Jason C
Eh bien, je donnerais +1 si vous parveniez à libérer la mémoire en cours de route (s'il vous plaît, envoyez-moi @une requête ping une fois que vous avez réussi, car je ne garderai probablement pas mon œil dessus).
Yo '22
0

Linux upstart init

À la lecture la plus stricte de la question, je pense que cela est impossible. Il s'agit essentiellement de demander à un programme de démarrer spontanément avec l'aide d'aucun autre programme en cours d'exécution.

Il y a quelques atet des chronréponses à base, mais avec la lecture plus stricte, atdet anacrondes programmes supplémentaires qui sont en cours d' exécution tout le temps, ils peuvent être disqualifiés.

Une approche similaire, mais un peu plus bas consiste à utiliser celle de Linux init. En tant que root, ajoutez ce fichier .conf à /etc/init/:

description "pour toujours"

commencer au niveau d'exécution [2345]
arrêtez-vous au niveau d'exécution [! 2345]

renaître

exec sommeil 10

Ensuite, initrelisez ses fichiers .conf:

sudo telinit 5

Cela lancera un sleepprocessus qui durera 10 secondes, puis se terminera. initréapparaîtra sleepdès que le précédent sera détecté.

Bien sûr, cela utilise toujours init comme programme supplémentaire. Vous pourriez soutenir que initc'est une extension logique du noyau et qu'il sera toujours disponible sous Linux.

Si cela n’est pas acceptable, alors je suppose que la tâche la plus basse à faire est de créer un module de noyau qui réapparaîtra dans un processus utilisateur (vous ne savez pas à quel point cela est facile). Ici, on peut affirmer que le noyau n'est pas un processus, et donc pas un programme (supplémentaire). D'autre part, le noyau est un programme à part entière, du point de vue de la CPU.

Trauma numérique
la source
-1

TI-BASIC: 5 caractères

appeler prgmA

:prgmA
scrblnrd3
la source
Je peux compter 6 caractères. Y a-t-il quelque chose de spécial dans le calcul de la taille du programme TI-BASIC?
pastebin.com slash 0mr8spkT
Il ne :s'agit que du symbole de début de ligne lorsque vous programmez dans TI-basic. Ce n'est pas quelque chose que vous tapez, c'est juste là dans l'éditeur.
scrblnrd3
Je vois, merci pour l'info
pastebin.com slash 0mr8spkT
N'est-ce pas une invocation récursive? Essayez d'incrémenter Aet d'utiliser une valeur comme base, vous verrez qu'il finira par sortir.
ζ--
Toutes les variables sont globales dans ti-basic, donc je ne suis pas sûr. Il se pourrait
scrblnrd3