Команда командной строки для езды на автомобиле команды после определенного количества времени

Вы можете использовать этот метод 1, который использует ClassLoader.

 /**
 * Scans all classes accessible from the context class loader which belong to the given package and subpackages.
 *
 * @param packageName The base package
 * @return The classes
 * @throws ClassNotFoundException
 * @throws IOException
 */
private static Class[] getClasses(String packageName)
        throws ClassNotFoundException, IOException {
    ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
    assert classLoader != null;
    String path = packageName.replace('.', '/');
    Enumeration resources = classLoader.getResources(path);
    List dirs = new ArrayList();
    while (resources.hasMoreElements()) {
        URL resource = resources.nextElement();
        dirs.add(new File(resource.getFile()));
    }
    ArrayList classes = new ArrayList();
    for (File directory : dirs) {
        classes.addAll(findClasses(directory, packageName));
    }
    return classes.toArray(new Class[classes.size()]);
}

/**
 * Recursive method used to find all classes in a given directory and subdirs.
 *
 * @param directory   The base directory
 * @param packageName The package name for classes found inside the base directory
 * @return The classes
 * @throws ClassNotFoundException
 */
private static List findClasses(File directory, String packageName) throws ClassNotFoundException {
    List classes = new ArrayList();
    if (!directory.exists()) {
        return classes;
    }
    File[] files = directory.listFiles();
    for (File file : files) {
        if (file.isDirectory()) {
            assert !file.getName().contains(".");
            classes.addAll(findClasses(file, packageName + "." + file.getName()));
        } else if (file.getName().endsWith(".class")) {
            classes.add(Class.forName(packageName + '.' + file.getName().substring(0, file.getName().length() - 6)));
        }
    }
    return classes;
}

__________ 1 Этот метод был взят из http: // фрагментов. dzone.com/posts/show/4831, который был архивирован через Интернет-архив, связанный с ним сейчас. Фрагмент также доступен в https://dzone.com/articles/get-all-classes-within-package .

52
задан Jonathan Leffler 2 March 2009 в 21:37
поделиться

10 ответов

Я пришел на вечеринку довольно поздно, но не вижу в ответах списка моих любимых трюков.

В * NIX аварийный сигнал (2) наследуется через execve (2) , а SIGALRM по умолчанию является критическим. Так что часто вы можете просто:

$ doalarm () { perl -e 'alarm shift; exec @ARGV' "$@"; } # define a helper function

$ doalarm 300 ./foo.sh args

или установить тривиальную оболочку C , чтобы сделать это за вас.

Преимущества Используется только один PID, и механизм прост. Вы не уничтожите не тот процесс, если, например, ./ foo.sh завершился «слишком быстро» и его PID был повторно использован. Вам не нужно, чтобы несколько подпроцессов оболочки работали согласованно, что может быть выполнено правильно, но довольно чревато гонками.

Недостатки Ограниченный по времени процесс не может управлять своим будильником (например, alarm (2) , ualarm (2) , setitimer (2) ), так как это, скорее всего, сбросит унаследованный сигнал тревоги. Очевидно, он также не может блокировать или игнорировать SIGALRM, хотя то же самое можно сказать о SIGINT, SIGTERM и т. Д. Для некоторых других подходов.

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

27
ответ дан 7 November 2019 в 09:05
поделиться

Небольшая модификация однострочника perl вернет статус выхода.

perl -e '$s = shift; $SIG{ALRM} = sub { print STDERR "Timeout!\n"; kill INT => $p; exit 77 }; exec(@ARGV) unless $p = fork; alarm $s; waitpid $p, 0; exit ($? >> 8)' 10 yes foo

Обычно exit ($? >> 8) пересылает статус выхода подпроцесса. Я просто выбрал 77 в статусе выхода для тайм-аута.

1
ответ дан 7 November 2019 в 09:05
поделиться

Попробуйте что-нибудь вроде:

# This function is called with a timeout (in seconds) and a pid.
# After the timeout expires, if the process still exists, it attempts
# to kill it.
function timeout() {
    sleep $1
    # kill -0 tests whether the process exists
    if kill -0 $2 > /dev/null 2>&1 ; then
        echo "killing process $2"
        kill $2 > /dev/null 2>&1
    else
        echo "process $2 already completed"
    fi
}

<your command> &
cpid=$!
timeout 3 $cpid
wait $cpid > /dev/null 2>&
exit $?

У этого есть обратная сторона: если pid вашего процесса повторно используется в течение тайм-аута, это может убить не тот процесс. Это маловероятно, но вы можете запускать более 20000 процессов в секунду. Это можно исправить.

2
ответ дан 7 November 2019 в 09:05
поделиться

Как насчет использования инструмента ожидания?

## run a command, aborting if timeout exceeded, e.g. timed-run 20 CMD ARGS ...
timed-run() {
  # timeout in seconds
  local tmout="$1"
  shift
  env CMD_TIMEOUT="$tmout" expect -f - "$@" <<"EOF"
# expect script follows
eval spawn -noecho $argv
set timeout $env(CMD_TIMEOUT)
expect {
   timeout {
      send_error "error: operation timed out\n"
      exit 1
   }
   eof
}
EOF
}
1
ответ дан 7 November 2019 в 09:05
поделиться

чистый bash:


#!/bin/bash

if [[ $# < 2 ]]; then
  echo "Usage: $0 timeout cmd [options]"
  exit 1
fi

TIMEOUT="$1"
shift

BOSSPID=$$

(
  sleep $TIMEOUT
  kill -9 -$BOSSPID
)&
TIMERPID=$!

trap "kill -9 $TIMERPID" EXIT

eval "$@"
1
ответ дан 7 November 2019 в 09:05
поделиться

Я использую "timelimit", это пакет, доступный в репозитории debian.

http://devel.ringlet.net/sysutils/timelimit/

2
ответ дан 7 November 2019 в 09:05
поделиться

Perl один лайнер, только для ударов:

perl -e '$s = shift; $SIG{ALRM} = sub { print STDERR "Timeout!\n"; kill INT => $p }; exec(@ARGV) unless $p = fork; alarm $s; waitpid $p, 0' 10 yes foo

Это печатает 'нечто' в течение десяти секунд, затем испытывает таймаут. Замените '10' любым числом секунд, и 'да нечто' с любой командой.

4
ответ дан vasi 7 November 2019 в 19:05
поделиться

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

ulimit -t 10

Пределы процесс к 10 секундам процессорного времени.

Для фактического использования его для ограничения нового процесса, а не текущего процесса можно хотеть использовать сценарий обертки:

#! /usr/bin/env python

import os
os.system("ulimit -t 10; other-command-here")

другая-команда может быть любым инструментом. Я выполнял Java, Python, C и версии Схемы различных алгоритмов сортировки и вход, сколько времени они взяли при ограничении времени выполнения 30 секундами. Приложение Python какао генерировало различные командные строки - включая аргументы - и сопоставило времена в файл CSV, но это был действительно просто пух сверх команды, обеспеченной выше.

11
ответ дан Matthew Schinckel 7 November 2019 в 19:05
поделиться

Возможно, я не понимаю вопроса, но это звучит выполнимым непосредственно, по крайней мере, в ударе:

( /path/to/slow command with options ) & sleep 5 ; kill $!

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

$! переменная является Bash, встроенным, который содержит идентификатор процесса последний раз запущенной подоболочки. Важно не иметь & в круглой скобке делая его тот путь теряет идентификатор процесса.

30
ответ дан unwind 7 November 2019 в 19:05
поделиться

У меня есть программа, названная timeout, который делает это - записанный в C, первоначально в 1989, но обновляемый периодически с тех пор.

<час> Обновление: этому коду не удается скомпилировать на MacOS X, потому что SIGRTMIN не определяется и перестал работать к тайм-ауту при выполнении на MacOS X, потому что эти signal() функция там возобновляется wait() после времен аварийного сигнала - который не является необходимым поведением. У меня есть новая версия timeout.c, который имеет дело с обеими этими проблемами (использующий sigaction() вместо signal()). Как прежде, свяжитесь со мной для 10K gzipped файл tar с исходным кодом и страницей руководства (см. мой профиль). <час>
/*
@(#)File:           $RCSfile: timeout.c,v $
@(#)Version:        $Revision: 4.6 $
@(#)Last changed:   $Date: 2007/03/01 22:23:02 $
@(#)Purpose:        Run command with timeout monitor
@(#)Author:         J Leffler
@(#)Copyright:      (C) JLSS 1989,1997,2003,2005-07
*/

#define _POSIX_SOURCE       /* Enable kill() in <unistd.h> on Solaris 7 */
#define _XOPEN_SOURCE 500

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include "stderr.h"

#define CHILD       0
#define FORKFAIL    -1

static const char usestr[] = "[-vV] -t time [-s signal] cmd [arg ...]";

#ifndef lint
/* Prevent over-aggressive optimizers from eliminating ID string */
const char jlss_id_timeout_c[] = "@(#)$Id: timeout.c,v 4.6 2007/03/01 22:23:02 jleffler Exp $";
#endif /* lint */

static void catcher(int signum)
{
    return;
}

int main(int argc, char **argv)
{
    pid_t   pid;
    int     tm_out;
    int     kill_signal;
    pid_t   corpse;
    int     status;
    int     opt;
    int     vflag = 0;

    err_setarg0(argv[0]);

    opterr = 0;
    tm_out = 0;
    kill_signal = SIGTERM;
    while ((opt = getopt(argc, argv, "vVt:s:")) != -1)
    {
        switch(opt)
        {
        case 'V':
            err_version("TIMEOUT", &"@(#)$Revision: 4.6 $ ($Date: 2007/03/01 22:23:02 $)"[4]);
            break;
        case 's':
            kill_signal = atoi(optarg);
            if (kill_signal <= 0 || kill_signal >= SIGRTMIN)
                err_error("signal number must be between 1 and %d\n", SIGRTMIN - 1);
            break;
        case 't':
            tm_out = atoi(optarg);
            if (tm_out <= 0)
                err_error("time must be greater than zero (%s)\n", optarg);
            break;
        case 'v':
            vflag = 1;
            break;
        default:
            err_usage(usestr);
            break;
        }
    }

    if (optind >= argc || tm_out == 0)
        err_usage(usestr);

    if ((pid = fork()) == FORKFAIL)
        err_syserr("failed to fork\n");
    else if (pid == CHILD)
    {
        execvp(argv[optind], &argv[optind]);
        err_syserr("failed to exec command %s\n", argv[optind]);
    }

    /* Must be parent -- wait for child to die */
    if (vflag)
        err_remark("time %d, signal %d, child PID %u\n", tm_out, kill_signal, (unsigned)pid);
    signal(SIGALRM, catcher);
    alarm((unsigned int)tm_out);
    while ((corpse = wait(&status)) != pid && errno != ECHILD)
    {
        if (errno == EINTR)
        {
            /* Timed out -- kill child */
            if (vflag)
                err_remark("timed out - send signal %d to process %d\n", (int)kill_signal, (int)pid);
            if (kill(pid, kill_signal) != 0)
                err_syserr("sending signal %d to PID %d - ", kill_signal, pid);
            corpse = wait(&status);
            break;
        }
    }

    alarm(0);
    if (vflag)
    {
        if (corpse == (pid_t) -1)
            err_syserr("no valid PID from waiting - ");
        else
            err_remark("child PID %u status 0x%04X\n", (unsigned)corpse, (unsigned)status);
    }

    if (corpse != pid)
        status = 2; /* Dunno what happened! */
    else if (WIFEXITED(status))
        status = WEXITSTATUS(status);
    else if (WIFSIGNALED(status))
        status = WTERMSIG(status);
    else
        status = 2; /* Dunno what happened! */

    return(status);
}

, Если Вы хотите 'официальный' код для 'stderr.h' и 'stderr.c', свяжитесь со мной (см. мой профиль).

12
ответ дан Jonathan Leffler 7 November 2019 в 19:05
поделиться
Другие вопросы по тегам:

Похожие вопросы: