kill 与killall

2023-05-16

【查询命令所属软件包】

        rpm -qf /usr/bin/killall

                psmisc-22.20-15.el7.x86_64

        rpm -qf /usr/bin/kill

                util-linux-2.23.2-65.el7_9.1.x86_64

【命令参数】

killallkill

  -e,--exact          require exact match for very long names

  -I,--ignore-case    case insensitive process name match

  -g,--process-group  kill process group instead of process

  -y,--younger-than   kill processes younger than TIME

  -o,--older-than     kill processes older than TIME

  -i,--interactive    ask for confirmation before killing

  -l,--list           list all known signal names

  -q,--quiet          don't print complaints

  -r,--regexp         interpret NAME as an extended regular expression

  -s,--signal SIGNAL  send this signal instead of SIGTERM

  -u,--user USER      kill only process(es) running as USER

  -v,--verbose        report if the signal was successfully sent

  -V,--version        display version information

  -w,--wait           wait for processes to die

  -Z,--context REGEXP kill only process(es) having context

                      (must precede other arguments)

--

【源码】

kill GitHub - util-linux/util-linux at v2.23.2

killall https://gitlab.com/psmisc/psmisc/-/tree/v22.20

killall 代码实现关键点:kill 调用,正则表达式匹配、虚拟目录(/proc/)枚举进程

/*
 * killall.c - kill processes by name or list PIDs
 *
 * Copyright (C) 1993-2002 Werner Almesberger
 * Copyright (C) 2002-2012 Craig Small
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */


#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <dirent.h>
#include <signal.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <getopt.h>
#include <pwd.h>
#include <regex.h>
#include <ctype.h>
#include <assert.h>

#ifdef WITH_SELINUX
#include <selinux/selinux.h>
#endif /*WITH_SELINUX*/

#ifdef HAVE_LOCALE_H
#include <locale.h>
#endif /* HAVE_LOCALE_H */

#include "i18n.h"
#include "comm.h"
#include "signals.h"

#define PROC_BASE "/proc"
#define MAX_NAMES (int)(sizeof(unsigned long)*8)

#define TSECOND "s"
#define TMINUTE "m"
#define THOUR   "h"
#define TDAY    "d" 
#define TWEEK   "w"
#define TMONTH  "M" 
#define TYEAR   "y"

#define TMAX_SECOND 31536000
#define TMAX_MINUTE 525600  
#define TMAX_HOUR   8760    
#define TMAX_DAY    365     
#define TMAX_WEEK   48      
#define TMAX_MONTH  12      
#define TMAX_YEAR   1       

#define ER_REGFAIL -1
#define ER_NOMEM   -2
#define ER_UNKWN   -3
#define ER_OOFRA   -4

static int verbose = 0, exact = 0, interactive = 0, reg = 0,
           quiet = 0, wait_until_dead = 0, process_group = 0,
           ignore_case = 0;
static long younger_than = 0, older_than = 0;

static int
ask (char *name, pid_t pid, const int signal)
{
  int res;
  size_t len;
  char *line;

  line = NULL;
  len = 0;

  do {
    if (signal == SIGTERM)
        printf (_("Kill %s(%s%d) ? (y/N) "), name, process_group ? "pgid " : "",
	        pid);
    else
        printf (_("Signal %s(%s%d) ? (y/N) "), name, process_group ? "pgid " : "",
	        pid);

    fflush (stdout);

    if (getline (&line, &len, stdin) < 0)
      return 0;
    /* Check for default */
    if (line[0] == '\n') {
      free(line);
      return 0;
    }
    res = rpmatch(line);
    if (res >= 0) {
      free(line);
      return res;
    }
  } while(1);
  /* Never should get here */
}

static double
uptime()
{
   char * savelocale;
   char buf[2048];
   FILE* file;
   if (!(file=fopen( PROC_BASE "/uptime", "r"))) {
      fprintf(stderr, "killall: error opening uptime file\n");	
      exit(1);
   }
   savelocale = setlocale(LC_NUMERIC, NULL);
   setlocale(LC_NUMERIC,"C");
   if (fscanf(file, "%2047s", buf) == EOF) perror("uptime");
   fclose(file);
   setlocale(LC_NUMERIC,savelocale);
   return atof(buf);
}

/* process age from jiffies to seconds via uptime */
static double process_age(const unsigned long long jf)
{
	double age;
	double sc_clk_tck = sysconf(_SC_CLK_TCK);
	assert(sc_clk_tck > 0);
	age = uptime() - jf / sc_clk_tck;
	if (age < 0L)
		return 0L;
	return age;
}

/* returns requested time interval in seconds, 
 negative indicates error has occurred
 */
static long
parse_time_units(const char* age)
{
   char *unit;
   long num;

   num = strtol(age,&unit,10);
   if (age == unit) /* no digits found */
     return -1;
   if (unit[0] == '\0') /* no units found */
     return -1;

   switch(unit[0]) {
   case 's':
     return num;
   case 'm':
     return (num * 60);
   case 'h':
     return (num * 60 * 60);
   case 'd':
     return (num * 60 * 60 * 24);
   case 'w':
     return (num * 60 * 60 * 24 * 7);
   case 'M':
     return (num * 60 * 60 * 24 * 7 * 4);
   case 'y':
     return (num * 60 * 60 * 24 * 7 * 4 * 12);
   }
   return -1;
}

static int
match_process_uid(pid_t pid, uid_t uid)
{
	char buf[128];
	uid_t puid;
	FILE *f;
	int re = -1;
	
	snprintf (buf, sizeof buf, PROC_BASE "/%d/status", pid);
	if (!(f = fopen (buf, "r")))
		return 0;
	
	while (fgets(buf, sizeof buf, f))
	{
		if (sscanf (buf, "Uid:\t%d", &puid))
		{
			re = uid==puid;
			break;
		}
	}
	fclose(f);
	if (re==-1)
	{
		fprintf(stderr, _("killall: Cannot get UID from process status\n"));
		exit(1);
	}
	return re;
}

static regex_t *
build_regexp_list(int names, char **namelist)
{
	int i;
	regex_t *reglist;
	int flag = REG_EXTENDED|REG_NOSUB;
	
	if (!(reglist = malloc (sizeof (regex_t) * names)))
	{
		perror ("malloc");
		exit (1);
	}

	if (ignore_case)
		flag |= REG_ICASE;
	
	for (i = 0; i < names; i++)
	{
		if (regcomp(&reglist[i], namelist[i], flag) != 0) 
		{
			fprintf(stderr, _("killall: Bad regular expression: %s\n"), namelist[i]);
			exit (1);
		}
	}
	return reglist;
}

#ifdef WITH_SELINUX
static int
kill_all(int signal, int names, char **namelist, struct passwd *pwent, 
					regex_t *scontext )
#else  /*WITH_SELINUX*/
static int
kill_all (int signal, int names, char **namelist, struct passwd *pwent)
#endif /*WITH_SELINUX*/
{
  DIR *dir;
  struct dirent *de;
  FILE *file;
  struct stat st, sts[MAX_NAMES];
  int *name_len = NULL;
  char *path, comm[COMM_LEN];
  char *command_buf;
  char *command;
  pid_t *pid_table, pid, self, *pid_killed;
  pid_t *pgids;
  int i, j, okay, length, got_long, error;
  int pids, max_pids, pids_killed;
  unsigned long found;
  regex_t *reglist = NULL;;
#ifdef WITH_SELINUX
  security_context_t lcontext=NULL;
#endif /*WITH_SELINUX*/

  if (names && reg) 
      reglist = build_regexp_list(names, namelist);
  else if (names)
   {
      if (!(name_len = malloc (sizeof (int) * names)))
        {
          perror ("malloc");
          exit (1);
        }
      for (i = 0; i < names; i++) 
        {
          if (!strchr (namelist[i], '/'))
            {
	      sts[i].st_dev = 0;
	      name_len[i] = strlen (namelist[i]);
            }
          else if (stat (namelist[i], &sts[i]) < 0)
            {
	      perror (namelist[i]);
	      exit (1);
            }
        }
    } 
  self = getpid ();
  found = 0;
  if (!(dir = opendir (PROC_BASE)))
    {
      perror (PROC_BASE);
      exit (1);
    }
  max_pids = 256;
  pid_table = malloc (max_pids * sizeof (pid_t));
  if (!pid_table)
    {
      perror ("malloc");
      exit (1);
    }
  pids = 0;
  while ( (de = readdir (dir)) != NULL)
    {
      if (!(pid = (pid_t) atoi (de->d_name)) || pid == self)
	continue;
      if (pids == max_pids)
	{
	  if (!(pid_table = realloc (pid_table, 2 * pids * sizeof (pid_t))))
	    {
	      perror ("realloc");
	      exit (1);
	    }
	  max_pids *= 2;
	}
      pid_table[pids++] = pid;
    }
  (void) closedir (dir);
  pids_killed = 0;
  pid_killed = malloc (max_pids * sizeof (pid_t));
  if (!pid_killed)
    {
      perror ("malloc");
      exit (1);
    }
  if (!process_group)
    pgids = NULL;		/* silence gcc */
  else
    {
      pgids = calloc (pids, sizeof (pid_t));
      if (!pgids)
	{
	  perror ("malloc");
	  exit (1);
	}
    }
  for (i = 0; i < pids; i++)
    {
      pid_t id;
      int found_name = -1;
      double process_age_sec = 0;
      /* match by UID */
      if (pwent && match_process_uid(pid_table[i], pwent->pw_uid)==0)
	continue;
#ifdef WITH_SELINUX
      /* match by SELinux context */
      if (scontext) 
        {
          if (getpidcon(pid_table[i], &lcontext) < 0)
            continue;
	  if (regexec(scontext, lcontext, 0, NULL, 0) != 0) {
            freecon(lcontext);
            continue;
          }
          freecon(lcontext);
        }
#endif /*WITH_SELINUX*/
      /* load process name */
      if (asprintf (&path, PROC_BASE "/%d/stat", pid_table[i]) < 0)
	continue;
      if (!(file = fopen (path, "r"))) 
	{
	  free (path);
	  continue;
	}
      free (path);
      okay = fscanf (file, "%*d (%15[^)]", comm) == 1;
      if (!okay) {
	fclose(file);
	continue;
      }
      if ( younger_than || older_than ) {
	 rewind(file);
	 unsigned long long proc_stt_jf = 0;
	 okay = fscanf(file, "%*d %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %Lu", 
		       &proc_stt_jf) == 1;
	 if (!okay) {
	    fclose(file);
	    continue;
	 }
	 process_age_sec = process_age(proc_stt_jf);
      }
      (void) fclose (file);
       
      got_long = 0;
      command = NULL;		/* make gcc happy */
      length = strlen (comm);
      if (length == COMM_LEN - 1)
	{
	  if (asprintf (&path, PROC_BASE "/%d/cmdline", pid_table[i]) < 0)
	    continue;
	  if (!(file = fopen (path, "r"))) {
	    free (path);
	    continue;
	  }
	  free (path);
          while (1) {
            /* look for actual command so we skip over initial "sh" if any */
            char *p;
	    int cmd_size = 128;
	    command_buf = (char *)malloc (cmd_size);
	    if (!command_buf)
	      exit (1);

            /* 'cmdline' has arguments separated by nulls */
            for (p=command_buf; ; p++) {
              int c;
	      if (p == (command_buf + cmd_size)) 
		{
		  int cur_size = cmd_size;
		  cmd_size *= 2;
		  command_buf = (char *)realloc(command_buf, cmd_size);
		  if (!command_buf)
		    exit (1);
		  p = command_buf + cur_size;
		}
              c = fgetc(file);
              if (c == EOF || c == '\0') {
                *p = '\0';
                break;
              } else {
                *p = c;
              }
            }
            if (strlen(command_buf) == 0) {
              okay = 0;
              break;
            }
            p = strrchr(command_buf,'/');
            p = p ? p+1 : command_buf;
            if (strncmp(p, comm, COMM_LEN-1) == 0) {
              okay = 1;
              command = p;
              break;
            }
          }
          (void) fclose(file);
	  if (exact && !okay)
	    {
	      if (verbose)
		fprintf (stderr, _("killall: skipping partial match %s(%d)\n"),
			comm, pid_table[i]);
	      continue;
	    }
	  got_long = okay;
	}
      /* mach by process name */
      for (j = 0; j < names; j++)
	{
	  if (reg)
	    {
	      if (regexec (&reglist[j], got_long ? command : comm, 0, NULL, 0) != 0)
		      continue;
	    }
	  else /* non-regex */
	    {
	      if ( younger_than && process_age_sec && (process_age_sec > younger_than ) )
		 continue;
	      if ( older_than   && process_age_sec && (process_age_sec < older_than ) )
		 continue;
	       
 	      if (!sts[j].st_dev)
	        {
	          if (length != COMM_LEN - 1 || name_len[j] < COMM_LEN - 1)
	  	    {
		      if (ignore_case == 1)
		        {
		          if (strcasecmp (namelist[j], comm))
		             continue;
		        }
		      else
		        {
		          if (strcmp(namelist[j], comm))
		             continue;
		        }
		    }
	          else
	            {
	              if (ignore_case == 1)
	                {
	                  if (got_long ? strcasecmp (namelist[j], command) :
	                                 strncasecmp (namelist[j], comm, COMM_LEN - 1))
	                     continue;
	                }
	              else
	                {
	                  if (got_long ? strcmp (namelist[j], command) :
	                                 strncmp (namelist[j], comm, COMM_LEN - 1))
	                     continue;
	                }
	            }
	        }
	      else
	        {
		  int ok = 1;

	          if (asprintf (&path, PROC_BASE "/%d/exe", pid_table[i]) < 0)
		    continue;

	          if (stat (path, &st) < 0) 
		      ok = 0;

		  else if (sts[j].st_dev != st.st_dev ||
			   sts[j].st_ino != st.st_ino)
		    {
		      /* maybe the binary has been modified and std[j].st_ino
		       * is not reliable anymore. We need to compare paths.
		       */
		      size_t len = strlen(namelist[j]);
		      char *linkbuf = malloc(len + 1);

		      if (!linkbuf ||
			  readlink(path, linkbuf, len + 1) != len ||
			  memcmp(namelist[j], linkbuf, len))
			ok = 0;
		      free(linkbuf);
		    }

		  free(path);
		  if (!ok)
		    continue;
	        }
	    } /* non-regex */
	  found_name = j;
	  break;
	}  
        
        if (names && found_name==-1)
	  continue;  /* match by process name faild */
	
        /* check for process group */
	if (!process_group)
	  id = pid_table[i];
	else
	  {
	    int j;

	    id = getpgid (pid_table[i]);
	    pgids[i] = id;
	    if (id < 0)
	      {
	        fprintf (stderr, "killall: getpgid(%d): %s\n",
			   pid_table[i], strerror (errno));
	      }
	    for (j = 0; j < i; j++)
	      if (pgids[j] == id)
	        break;
	    if (j < i)
	      continue;
	  }	
	if (interactive && !ask (comm, id, signal))
	  continue;
	if (kill (process_group ? -id : id, signal) >= 0)
	  {
	    if (verbose)
	      fprintf (stderr, _("Killed %s(%s%d) with signal %d\n"), got_long ? command :
			 comm, process_group ? "pgid " : "", id, signal);
	    if (found_name >= 0)
		    /* mark item of namelist */
		    found |= 1 << found_name;
	    pid_killed[pids_killed++] = id;
	  }
	else if (errno != ESRCH || interactive)
	  fprintf (stderr, "%s(%d): %s\n", got_long ? command :
	    	comm, id, strerror (errno));
    }
  if (!quiet)
    for (i = 0; i < names; i++)
      if (!(found & (1 << i)))
	fprintf (stderr, _("%s: no process found\n"), namelist[i]);
  if (names)
    /* killall returns a zero return code if at least one process has 
     * been killed for each listed command. */
    error = found == ((1 << (names - 1)) | ((1 << (names - 1)) - 1)) ? 0 : 1;
  else
    /* in nameless mode killall returns a zero return code if at least 
     * one process has killed */
    error = pids_killed ? 0 : 1;
  /*
   * We scan all (supposedly) killed processes every second to detect dead
   * processes as soon as possible in order to limit problems of race with
   * PID re-use.
   */
  while (pids_killed && wait_until_dead)
    {
      for (i = 0; i < pids_killed;)
	{
	  if (kill (process_group ? -pid_killed[i] : pid_killed[i], 0) < 0 &&
	      errno == ESRCH)
	    {
	      pid_killed[i] = pid_killed[--pids_killed];
	      continue;
	    }
	  i++;
	}
      sleep (1);		/* wait a bit longer */
    }
  return error;
}


static void
usage (const char *msg)
{
  if (msg != NULL)
    fprintf(stderr, "%s\n", msg);
#ifdef WITH_SELINUX
   fprintf(stderr, _(
     "Usage: killall [-Z CONTEXT] [-u USER] [ -eIgiqrvw ] [ -SIGNAL ] NAME...\n"));
#else  /*WITH_SELINUX*/
  fprintf(stderr, _(
    "Usage: killall [OPTION]... [--] NAME...\n"));
#endif /*WITH_SELINUX*/
  fprintf(stderr, _(
    "       killall -l, --list\n"
    "       killall -V, --version\n\n"
    "  -e,--exact          require exact match for very long names\n"
    "  -I,--ignore-case    case insensitive process name match\n"
    "  -g,--process-group  kill process group instead of process\n"
    "  -y,--younger-than   kill processes younger than TIME\n"
    "  -o,--older-than     kill processes older than TIME\n"		    
    "  -i,--interactive    ask for confirmation before killing\n"
    "  -l,--list           list all known signal names\n"
    "  -q,--quiet          don't print complaints\n"
    "  -r,--regexp         interpret NAME as an extended regular expression\n"
    "  -s,--signal SIGNAL  send this signal instead of SIGTERM\n"
    "  -u,--user USER      kill only process(es) running as USER\n"
    "  -v,--verbose        report if the signal was successfully sent\n"
    "  -V,--version        display version information\n"
    "  -w,--wait           wait for processes to die\n"));
#ifdef WITH_SELINUX
  fprintf(stderr, _(
    "  -Z,--context REGEXP kill only process(es) having context\n"
    "                      (must precede other arguments)\n"));
#endif /*WITH_SELINUX*/
  fputc('\n', stderr);
  exit(1);
}


void print_version()
{
  fprintf(stderr, "killall (PSmisc) %s\n", VERSION);
  fprintf(stderr, _(
    "Copyright (C) 1993-2012 Werner Almesberger and Craig Small\n\n"));
  fprintf(stderr, _(
    "PSmisc comes with ABSOLUTELY NO WARRANTY.\n"
    "This is free software, and you are welcome to redistribute it under\n"
    "the terms of the GNU General Public License.\n"
    "For more information about these matters, see the files named COPYING.\n"));
}

static int
have_proc_self_stat (void)
{
  char filename[128];
  struct stat isproc;
  pid_t pid = getpid();

  snprintf(filename, sizeof(filename), PROC_BASE"/%d/stat", (int) pid);
  return stat(filename, &isproc) == 0;
}

int
main (int argc, char **argv)
{
  char *name;
  int sig_num;
  int optc;
  int myoptind;
  struct passwd *pwent = NULL;
  char yt[16];
  char ot[16];

  //int optsig = 0;

  struct option options[] = {
    {"exact", 0, NULL, 'e'},
    {"ignore-case", 0, NULL, 'I'},
    {"process-group", 0, NULL, 'g'},
    {"younger-than", 1, NULL, 'y'},
    {"older-than", 1, NULL, 'o'},
    {"interactive", 0, NULL, 'i'},
    {"list-signals", 0, NULL, 'l'},
    {"quiet", 0, NULL, 'q'},
    {"regexp", 0, NULL, 'r'},
    {"signal", 1, NULL, 's'},
    {"user", 1, NULL, 'u'},
    {"verbose", 0, NULL, 'v'},
    {"wait", 0, NULL, 'w'},
#ifdef WITH_SELINUX
    {"context", 1, NULL, 'Z'},
#endif /*WITH_SELINUX*/
    {"version", 0, NULL, 'V'},
    {0,0,0,0 }};

  /* Setup the i18n */
#ifdef ENABLE_NLS
  setlocale(LC_ALL, "");
  bindtextdomain(PACKAGE, LOCALEDIR);
  textdomain(PACKAGE);
#endif
#ifdef WITH_SELINUX
  security_context_t scontext = NULL;
  regex_t scontext_reg;

  if ( argc < 2 ) usage(NULL); /* do the obvious thing... */
#endif /*WITH_SELINUX*/

  name = strrchr (*argv, '/');
  if (name)
    name++;
  else
    name = *argv;
  sig_num = SIGTERM;


  opterr = 0;
#ifdef WITH_SELINUX
  while ( (optc = getopt_long_only(argc,argv,"egy:o:ilqrs:u:vwZ:VI",options,NULL)) != -1) {
#else
  while ( (optc = getopt_long_only(argc,argv,"egy:o:ilqrs:u:vwVI",options,NULL)) != -1) {
#endif
    switch (optc) {
    case 'e':
      exact = 1;
      break;
    case 'g':
      process_group = 1;
      break;
    case 'y':
      strncpy(yt, optarg, 16);
	  yt[15] = '\0';
      if ( 0 >= (younger_than = parse_time_units(yt) ) )
	    usage(_("Invalid time format"));
      break;
    case 'o':
      strncpy(ot, optarg, 16);
	  ot[15] = '\0';
      if ( 0 >= (older_than = parse_time_units(ot) ) )
	    usage(_("Invalid time format"));
      break;
    case 'i':
      interactive = 1;
      break;
    case 'l':
      list_signals();
      return 0;
      break;
    case 'q':
      quiet = 1;
      break;
    case 'r':
	  reg = 1;
	  break;
    case 's':
	  sig_num = get_signal (optarg, "killall");
      break;
    case 'u':
      if (!(pwent = getpwnam(optarg))) {
        fprintf (stderr, _("Cannot find user %s\n"), optarg);
        exit (1);
      }
      break;
    case 'v':
      verbose = 1;
      break;
    case 'w':
      wait_until_dead = 1;
      break;
    case 'I':
      /* option check is optind-1 but sig name is optind */
      if (strcmp(argv[optind-1],"-I") == 0 || strncmp(argv[optind-1],"--",2) == 0) {
        ignore_case = 1;
      } else {
	      sig_num = get_signal (argv[optind]+1, "killall");
      }
      break;
    case 'V':
      /* option check is optind-1 but sig name is optind */
      if (strcmp(argv[optind-1],"-V") == 0 || strncmp(argv[optind-1],"--",2) == 0) {
        print_version();
        return 0;
      }
	    sig_num = get_signal (argv[optind]+1, "killall");
      break;
#ifdef WITH_SELINUX
    case 'Z': 
      if (is_selinux_enabled()>0) {
	    scontext=optarg;
        if (regcomp(&scontext_reg, scontext, REG_EXTENDED|REG_NOSUB) != 0) {
          fprintf(stderr, _("Bad regular expression: %s\n"), scontext);
          exit (1);
	    }
      } else 
        fprintf(stderr, "Warning: -Z (--context) ignored. Requires an SELinux enabled kernel\n");
      break;
#endif /*WITH_SELINUX*/
    case '?':
      /* Signal names are in uppercase, so check to see if the argv
       * is upper case */
      if (argv[optind-1][1] >= 'A' && argv[optind-1][1] <= 'Z') {
	    sig_num = get_signal (argv[optind-1]+1, "killall");
      } else {
        /* Might also be a -## signal too */
        if (argv[optind-1][1] >= '0' && argv[optind-1][1] <= '9') {
          sig_num = atoi(argv[optind-1]+1);
        } else {
          usage(NULL);
        }
      }
      break;
    }
  }
  myoptind = optind;
#ifdef WITH_SELINUX
  if ((argc - myoptind < 1) && pwent==NULL && scontext==NULL) 
#else
  if ((argc - myoptind < 1) && pwent==NULL)	  
#endif
    usage(NULL);

  if (argc - myoptind > MAX_NAMES) {
    fprintf (stderr, _("killall: Maximum number of names is %d\n"),
	   MAX_NAMES);
    exit (1);
  }
  if (!have_proc_self_stat()) {
    fprintf (stderr, _("killall: %s lacks process entries (not mounted ?)\n"),
		PROC_BASE);
    exit (1);
  }
  argv = argv + myoptind;
  /*printf("sending signal %d to procs\n", sig_num);*/
#ifdef WITH_SELINUX
  return kill_all(sig_num,argc - myoptind, argv, pwent, 
		  		scontext ? &scontext_reg : NULL);
#else  /*WITH_SELINUX*/
  return kill_all(sig_num,argc - myoptind, argv, pwent);
#endif /*WITH_SELINUX*/
}

kill 代码关键点:kill 调用

/*
 * Copyright (c) 1988, 1993, 1994
 *	The Regents of the University of California.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *	This product includes software developed by the University of
 *	California, Berkeley and its contributors.
 * 4. Neither the name of the University nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */
/*
 *  oct 5 1994 -- almost entirely re-written to allow for process names.
 *  modifications (c) salvatore valente <svalente@mit.edu>
 *  may be used / modified / distributed under the same terms as the original.
 *
 *  1999-02-22 Arkadiusz Miśkiewicz <misiek@pld.ORG.PL>
 *  - added Native Language Support
 *
 *  1999-11-13 aeb Accept signal numers 128+s.
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>		/* for isdigit() */
#include <unistd.h>
#include <signal.h>

#include "c.h"
#include "nls.h"
#include "closestream.h"
#include "procutils.h"
#include "strutils.h"
#include "ttyutils.h"
#include "xalloc.h"

struct signv {
	const char *name;
	int val;
} sys_signame[] = {
	/* POSIX signals */
	{ "HUP",	SIGHUP },	/* 1 */
	{ "INT",	SIGINT }, 	/* 2 */
	{ "QUIT",	SIGQUIT }, 	/* 3 */
	{ "ILL",	SIGILL }, 	/* 4 */
#ifdef SIGTRAP
	{ "TRAP",	SIGTRAP },	/* 5 */
#endif
	{ "ABRT",	SIGABRT }, 	/* 6 */
#ifdef SIGIOT
	{ "IOT",	SIGIOT }, 	/* 6, same as SIGABRT */
#endif
#ifdef SIGEMT
	{ "EMT",	SIGEMT }, 	/* 7 (mips,alpha,sparc*) */
#endif
#ifdef SIGBUS
	{ "BUS",	SIGBUS },	/* 7 (arm,i386,m68k,ppc), 10 (mips,alpha,sparc*) */
#endif
	{ "FPE",	SIGFPE }, 	/* 8 */
	{ "KILL",	SIGKILL }, 	/* 9 */
	{ "USR1",	SIGUSR1 }, 	/* 10 (arm,i386,m68k,ppc), 30 (alpha,sparc*), 16 (mips) */
	{ "SEGV",	SIGSEGV }, 	/* 11 */
	{ "USR2",	SIGUSR2 }, 	/* 12 (arm,i386,m68k,ppc), 31 (alpha,sparc*), 17 (mips) */
	{ "PIPE",	SIGPIPE }, 	/* 13 */
	{ "ALRM",	SIGALRM }, 	/* 14 */
	{ "TERM",	SIGTERM }, 	/* 15 */
#ifdef SIGSTKFLT
	{ "STKFLT",	SIGSTKFLT },	/* 16 (arm,i386,m68k,ppc) */
#endif
	{ "CHLD",	SIGCHLD }, 	/* 17 (arm,i386,m68k,ppc), 20 (alpha,sparc*), 18 (mips) */
#ifdef SIGCLD
	{ "CLD",	SIGCLD },	/* same as SIGCHLD (mips) */
#endif
	{ "CONT",	SIGCONT }, 	/* 18 (arm,i386,m68k,ppc), 19 (alpha,sparc*), 25 (mips) */
	{ "STOP",	SIGSTOP },	/* 19 (arm,i386,m68k,ppc), 17 (alpha,sparc*), 23 (mips) */
	{ "TSTP",	SIGTSTP },	/* 20 (arm,i386,m68k,ppc), 18 (alpha,sparc*), 24 (mips) */
	{ "TTIN",	SIGTTIN },	/* 21 (arm,i386,m68k,ppc,alpha,sparc*), 26 (mips) */
	{ "TTOU",	SIGTTOU },	/* 22 (arm,i386,m68k,ppc,alpha,sparc*), 27 (mips) */
#ifdef SIGURG
	{ "URG",	SIGURG },	/* 23 (arm,i386,m68k,ppc), 16 (alpha,sparc*), 21 (mips) */
#endif
#ifdef SIGXCPU
	{ "XCPU",	SIGXCPU },	/* 24 (arm,i386,m68k,ppc,alpha,sparc*), 30 (mips) */
#endif
#ifdef SIGXFSZ
	{ "XFSZ",	SIGXFSZ },	/* 25 (arm,i386,m68k,ppc,alpha,sparc*), 31 (mips) */
#endif
#ifdef SIGVTALRM
	{ "VTALRM",	SIGVTALRM },	/* 26 (arm,i386,m68k,ppc,alpha,sparc*), 28 (mips) */
#endif
#ifdef SIGPROF
	{ "PROF",	SIGPROF },	/* 27 (arm,i386,m68k,ppc,alpha,sparc*), 29 (mips) */
#endif
#ifdef SIGWINCH
	{ "WINCH",	SIGWINCH },	/* 28 (arm,i386,m68k,ppc,alpha,sparc*), 20 (mips) */
#endif
#ifdef SIGIO
	{ "IO",		SIGIO },	/* 29 (arm,i386,m68k,ppc), 23 (alpha,sparc*), 22 (mips) */
#endif
#ifdef SIGPOLL
	{ "POLL",	SIGPOLL },	/* same as SIGIO */
#endif
#ifdef SIGINFO
	{ "INFO",	SIGINFO },	/* 29 (alpha) */
#endif
#ifdef SIGLOST
	{ "LOST",	SIGLOST }, 	/* 29 (arm,i386,m68k,ppc,sparc*) */
#endif
#ifdef SIGPWR
	{ "PWR",	SIGPWR },	/* 30 (arm,i386,m68k,ppc), 29 (alpha,sparc*), 19 (mips) */
#endif
#ifdef SIGUNUSED
	{ "UNUSED",	SIGUNUSED },	/* 31 (arm,i386,m68k,ppc) */
#endif
#ifdef SIGSYS
	{ "SYS",	SIGSYS }, 	/* 31 (mips,alpha,sparc*) */
#endif
};

static int arg_to_signum (char *arg, int mask);
static void nosig (char *name);
static void printsig (int sig);
static void printsignals (FILE *fp, int pretty);
static int usage (int status);
static int kill_verbose (char *procname, int pid, int sig);

#ifdef HAVE_SIGQUEUE
static int use_sigval;
static union sigval sigdata;
#endif

int main (int argc, char *argv[])
{
    int errors, numsig, pid;
    char *ep, *arg;
    int do_pid, do_kill, check_all;

    setlocale(LC_ALL, "");
    bindtextdomain(PACKAGE, LOCALEDIR);
    textdomain(PACKAGE);
    atexit(close_stdout);

    numsig = SIGTERM;
    do_pid = (! strcmp (program_invocation_short_name, "pid")); 	/* Yecch */
    do_kill = 0;
    check_all = 0;

    /*  loop through the arguments.
	actually, -a is the only option can be used with other options.
	`kill' is basically a one-option-at-most program.  */
    for (argc--, argv++; argc > 0; argc--, argv++) {
	arg = *argv;
	if (*arg != '-') {
	    break;
	}
	if (! strcmp (arg, "--")) {
	    argc--, argv++;
	    break;
	}
	if (! strcmp (arg, "-v") || ! strcmp (arg, "-V") ||
	    ! strcmp (arg, "--version")) {
	    printf(UTIL_LINUX_VERSION);
	    return EXIT_SUCCESS;
	}
	if (! strcmp (arg, "-h") || ! strcmp (arg, "--help"))
	    return usage(EXIT_FAILURE);

	if (! strcmp (arg, "-a") || ! strcmp (arg, "--all")) {
	    check_all++;
	    continue;
	}
	if (! strcmp (arg, "-l") || ! strcmp (arg, "--list")) {
	    if (argc < 2) {
		printsignals (stdout, 0);
		return EXIT_SUCCESS;
	    }
	    if (argc > 2)
		return usage (EXIT_FAILURE);
	    /* argc == 2, accept "kill -l $?" */
	    arg = argv[1];
	    if ((numsig = arg_to_signum (arg, 1)) < 0)
		errx(EXIT_FAILURE, _("unknown signal: %s"), arg);
	    printsig (numsig);
	    return EXIT_SUCCESS;
	}
	/* for compatibility with procps kill(1) */
	if (! strncmp (arg, "--list=", 7) || ! strncmp (arg, "-l=", 3)) {
		char *p = strchr(arg, '=') + 1;
		if ((numsig = arg_to_signum(p, 1)) < 0)
			errx(EXIT_FAILURE, _("unknown signal: %s"), p);
		printsig (numsig);
		return EXIT_SUCCESS;
	}
	if (! strcmp (arg, "-L") || ! strcmp (arg, "--table")) {
	    printsignals (stdout, 1);
	    return EXIT_SUCCESS;
	}
	if (! strcmp (arg, "-p") || ! strcmp (arg, "--pid")) {
	    do_pid++;
	    if (do_kill)
		return usage (EXIT_FAILURE);
	    continue;
	}
	if (! strcmp (arg, "-s") || ! strcmp (arg, "--signal")) {
	    if (argc < 2) {
		return usage (EXIT_FAILURE);
	    }
	    do_kill++;
	    if (do_pid)
		return usage (EXIT_FAILURE);
	    argc--, argv++;
	    arg = *argv;
	    if ((numsig = arg_to_signum (arg, 0)) < 0) {
		nosig (arg);
		return EXIT_FAILURE;
	    }
	    continue;
	}
	if (! strcmp (arg, "-q") || ! strcmp (arg, "--queue")) {
	    if (argc < 2)
		return usage (EXIT_FAILURE);
	    argc--, argv++;
	    arg = *argv;
#ifdef HAVE_SIGQUEUE
	    sigdata.sival_int = strtos32_or_err(arg, _("invalid sigval argument"));
	    use_sigval = 1;
#endif
	    continue;
	}
	/*  `arg' begins with a dash but is not a known option.
	    so it's probably something like -HUP, or -1/-n
	    try to deal with it.
	    -n could be signal n, or pid -n (i.e. process group n).
	    In case of doubt POSIX tells us to assume a signal.
	    If a signal has been parsed, assume it's a pid, break */
	if (do_kill)
	  break;
	arg++;
	if ((numsig = arg_to_signum (arg, 0)) < 0) {
	    return usage (EXIT_FAILURE);
	}
	do_kill++;
	if (do_pid)
	    return usage (EXIT_FAILURE);
	continue;
    }

    if (! *argv) {
	return usage (EXIT_FAILURE);
    }
    if (do_pid) {
	numsig = -1;
    }

    /*  we're done with the options.
	the rest of the arguments should be process ids and names.
	kill them.  */
    for (errors = 0; (arg = *argv) != NULL; argv++) {
	pid = strtol (arg, &ep, 10);
	if (! *ep)
	    errors += kill_verbose (arg, pid, numsig);
	else  {
	    struct proc_processes *ps = proc_open_processes();
	    int ct = 0;

	    if (!ps)
	        continue;

	    if (!check_all)
		proc_processes_filter_by_uid(ps, getuid());

	    proc_processes_filter_by_name(ps, arg);

	    while (proc_next_pid(ps, &pid) == 0) {
		errors += kill_verbose(arg, pid, numsig);
		ct++;
	    }

	    if (!ct) {
		errors++;
		warnx (_("cannot find process \"%s\""), arg);
	    }
	    proc_close_processes(ps);
	}
    }
    if (errors != 0)
	errors = EXIT_FAILURE;
    return errors;
}

#ifdef SIGRTMIN
static int rtsig_to_signum(char *sig)
{
	int num, maxi = 0;
	char *ep = NULL;

	if (strncasecmp(sig, "min+", 4) == 0)
		sig += 4;
	else if (strncasecmp(sig, "max-", 4) == 0) {
		sig += 4;
		maxi = 1;
	}

	if (!isdigit(*sig))
		return -1;

	errno = 0;
	num = strtol(sig, &ep, 10);
	if (!ep || sig == ep || errno || num < 0)
		return -1;

	num = maxi ? SIGRTMAX - num : SIGRTMIN + num;

	if (num < SIGRTMIN || num > SIGRTMAX)
		return -1;

	return num;
}
#endif

static int signame_to_signum (char *sig)
{
    size_t n;

    if (! strncasecmp (sig, "sig", 3))
	sig += 3;

#ifdef SIGRTMIN
    /* RT signals */
    if (!strncasecmp(sig, "rt", 2))
	return rtsig_to_signum(sig + 2);
#endif
    /* Normal sugnals */
    for (n = 0; n < ARRAY_SIZE(sys_signame); n++) {
	if (! strcasecmp (sys_signame[n].name, sig))
	    return sys_signame[n].val;
    }
    return (-1);
}

static int arg_to_signum (char *arg, int maskbit)
{
    int numsig;
    char *ep;

    if (isdigit (*arg)) {
	numsig = strtol (arg, &ep, 10);
	if (numsig >= NSIG && maskbit && (numsig & 128) != 0)
	    numsig -= 128;
	if (*ep != 0 || numsig < 0 || numsig >= NSIG)
	    return (-1);
	return (numsig);
    }
    return signame_to_signum (arg);
}

static void nosig (char *name)
{
    warnx (_("unknown signal %s; valid signals:"), name);
    printsignals (stderr, 1);
}

static void printsig (int sig)
{
    size_t n;

    for (n = 0; n < ARRAY_SIZE(sys_signame); n++) {
	if (sys_signame[n].val == sig) {
	    printf ("%s\n", sys_signame[n].name);
	    return;
	}
    }
#ifdef SIGRTMIN
    if (sig >= SIGRTMIN && sig <= SIGRTMAX) {
	printf ("RT%d\n", sig - SIGRTMIN);
	return;
    }
#endif
    printf("%d\n", sig);
}

#define FIELD_WIDTH 11
static void pretty_print_signal(FILE *fp, size_t term_width, size_t *lpos,
				int signum, const char *name)
{
	if (term_width < (*lpos + FIELD_WIDTH)) {
	    fputc ('\n', fp);
	    *lpos = 0;
	}
	*lpos += FIELD_WIDTH;
	fprintf (fp, "%2d %-8s", signum, name);
}

static void printsignals (FILE *fp, int pretty)
{
    size_t n, lth, lpos = 0, width;

    if (!pretty) {
	for (n = 0; n < ARRAY_SIZE(sys_signame); n++) {
	    lth = 1+strlen(sys_signame[n].name);
	    if (lpos+lth > 72) {
		fputc ('\n', fp);
		lpos = 0;
	    } else if (lpos)
		fputc (' ', fp);
	    lpos += lth;
	    fputs (sys_signame[n].name, fp);
	}
#ifdef SIGRTMIN
	fputs (" RT<N> RTMIN+<N> RTMAX-<N>", fp);
#endif
	fputc ('\n', fp);
	return;
    }
    /* pretty print */
    width = get_terminal_width();
    if (width == 0)
	width = 72;
    else
	width -= 1;

    for (n = 0; n < ARRAY_SIZE(sys_signame); n++)
	    pretty_print_signal(fp, width, &lpos,
			    sys_signame[n].val, sys_signame[n].name);

#ifdef SIGRTMIN
    pretty_print_signal(fp, width, &lpos, SIGRTMIN, "RTMIN");
    pretty_print_signal(fp, width, &lpos, SIGRTMAX, "RTMAX");
#endif
    fputc ('\n', fp);
}

static int usage(int status)
{
	FILE *out = (status == 0 ? stdout : stderr);

	fputs(USAGE_HEADER, out);
	fprintf(out, _(" %s [options] <pid|name> [...]\n"), program_invocation_short_name);
	fputs(USAGE_OPTIONS, out);
	fputs(_(" -a, --all              do not restrict the name-to-pid conversion to processes\n"
		"                        with the same uid as the present process\n"), out);
	fputs(_(" -s, --signal <sig>     send specified signal\n"), out);
	fputs(_(" -q, --queue <sig>      use sigqueue(2) rather than kill(2)\n"), out);
	fputs(_(" -p, --pid              print pids without signaling them\n"), out);
	fputs(_(" -l, --list [=<signal>] list signal names, or convert one to a name\n"), out);
	fputs(_(" -L, --table            list signal names and numbers\n"), out);
	fputs(USAGE_SEPARATOR, out);
	fputs(USAGE_HELP, out);
	fputs(USAGE_VERSION, out);
	fprintf(out, USAGE_MAN_TAIL("kill(1)"));

	return status;
}

static int kill_verbose (char *procname, pid_t pid, int sig)
{
    int rc = 0;

    if (sig < 0) {
	printf ("%ld\n", (long)pid);
	return 0;
    }
#ifdef HAVE_SIGQUEUE
    if (use_sigval)
	rc = sigqueue(pid, sig, sigdata);
    else
#endif
	rc = kill (pid, sig);

    if (rc < 0) {
	warn(_("sending signal to %s failed"), procname);
	return 1;
    }
    return 0;
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

kill 与killall 的相关文章

  • Linux进程详解(非常详细且入门)---ps、top、kill、fg

    常见的操作系统都支持多重任务处理 multitasking 系统通过快速切换运行中的程序来实现多任务的同时执行 Linux内核通过使用进程来管理多重任务 进程是Linux用来安排不同程序等待CPU调度的一种组织方式 1 进程如何工作 系统启
  • linux kill一个指定进程脚本

    使用awk span class token shebang important bin bash span span class token comment echo 34 1 34 span span class token assig
  • 如何在 Linux 中终止进程

    您是否遇到过这样的情况 您启动了一个应用程序 但在使用该应用程序时突然变得无响应并意外崩溃 您尝试再次启动应用程序 但没有任何反应 因为原始应用程序进程从未真正完全关闭 好吧 我们所有人都曾在某个时刻发生过这种事 不是吗 解决方案是终止或终
  • std::shared_ptr 和 std::weak_ptr的用法以及引用计数的循环引用问题

    在std shared ptr被引入之前 C 标准库中实现的用于管理资源的智能指针只有std auto ptr一个而已 std auto ptr的作用非常有限 因为它存在被管理资源的所有权转移问题 这导致多个std auto ptr类型的局
  • linux信号通信总结

    http www ibm com developerworks cn linux l ipc part2 index1 html http www ibm com developerworks cn linux l ipc part2 in
  • ORACLE如何停止一个JOB

    ORACLE如何停止一个JOB 1 相关表 视图 dba jobs all jobs user jobs 包含登录用户所有的JOB信息 dba jobs running 包含正在运行job相关信息 注意 须使用oracle的sys用户登录到
  • 如何使用 C 在 Linux 上以编程方式终止进程树

    我正在尝试编写一个函数来生成一个子进程 让它运行一段时间 然后在它尚未完成时杀死它 int sysExecTimeout const char exePath int timeoutSec 在函数中 我使用fork and execl生成孩
  • 确保子进程在退出 Python 程序时死亡

    有没有办法确保所有创建的子进程在Python程序退出时都死掉 我所说的子进程是指那些使用 subprocess Popen 创建的进程 如果不是 我是否应该迭代所有发出的kills 然后kills 9 有什么更干净的吗 您可以使用atexi
  • 当收到来自“killall”或“kill -p pid”的终止信号时,如何在退出程序之前执行处理程序函数?

    我有以下代码 include
  • 从 C# 关闭最小化/图标化进程

    这是我的问题 我需要从 C 程序关闭一个已经运行的进程 问题是该进程现在作为图标运行 最小化到任务栏 除非用户至少打开它一次 这在无人值守的计算机上永远不会发生 否则它永远不会 有一个主窗口 我的另一个要求是应用程序是closed not
  • 如何用 Objective C 杀死一个线程?

    我调用了一个第三方 C 库 我已将其放入其自己的线程中 当前使用 NSThread 我想让用户能够停止该线程的执行 我很清楚这可能会导致的所有问题 但我仍然希望这样做 根据Apple 的线程编程指南 Cocoa 有可能这样做 iPhone
  • 如何杀死一个javascript函数?

    示例代码 var isExecutionOver false myFunction function does some asynchronous stuff and sets isExecutionOver to true when th
  • 从终端杀死 iOS 模拟器

    我试图从终端控制台终止 iOS 模拟器 在 Jenkins 中集成自动 UI 测试所需 但每次我尝试以下命令时 killall SimulatorBridge a prompt waiting for action gets display
  • 使用php杀死Linux中的用户进程

    我正在尝试编写一个 php 脚本来杀死 redhat 机器中的用户 我知道有可能 而且非常不安全 让apache能够以root身份执行操作 但我需要能够从网页上杀死任何用户 是否有人有任何好的工作脚本或给我指出一个地方找到更多信息吗 我可以
  • Linux:杀死后台任务

    如何终止 Linux 中最后生成的后台任务 Example doSomething doAnotherThing doB doC doD kill doB 你可以通过工作号码杀人 当您将任务置于后台时 您会看到类似以下内容的内容 scrip
  • 如何终止由 Ant 启动的失控 Java 进程?

    如果我从 ant 脚本启动一个分叉的 java 进程并终止该 ant 进程 它不会终止该 java 进程 无论是从 IDE 还是从命令行运行都是如此
  • 通过管道id杀死linux进程

    我想杀死一个进程并通过以下方式获取它的 id pgrep f python myscript py 我想打电话 kill s SIGINT 对此 但我找不到任何方法来做到这一点 该命令需要在一行中 尝试使用反引号运算符来评估子命令 kill
  • linux shell 终止信号 SIGKILL && KILL

    我刚刚写了一个shell脚本来控制模块的启动和停止 一切看起来都很正常 直到我发现停止命令导致了意想不到的结果 我使用命令kill s SIGKILL gpid杀死一组进程 我用 bin sh像这样运行命令 bin sh c kill s
  • Kill - 它会立即终止进程吗?

    什么是kill到底是怎么做的 我有一个父进程 它正在一个接一个地创建 100 个 作为示例 子进程 在任何孩子的工作结束时 我都会杀死孩子kill pid of child SIGKILL 我看不到ps输出 但是如果父进程出现问题并且我退出
  • 使用请求和多处理时的奇怪问题

    请检查这个Python代码 usr bin env python import requests import multiprocessing from time import sleep time from requests import

随机推荐

  • C++中的qsort、sort排序

    注意 xff1a int char string之类的是可以之间使用 gt lt 61 61 之类的进行判断 xff0c char 类型的使用strcmp就行了 而struct与vector都可以当做数组进行处理 xff0c cmp函数传递
  • 迷宫问题(牛客)

    题目描述 xff1a 定义一个二维数组N M xff08 其中2 lt 61 N lt 61 10 2 lt 61 M lt 61 10 xff09 xff0c 如5 5数组下所示 xff1a int maze 5 5 61 0 1 0 0
  • 查找兄弟单词(牛客)

    题目描述 xff1a 兄弟单词 xff1a 给定一个单词X xff0c 如果通过任意交换单词中字母的位置得到的新的单词Y xff0c 那么称X和Y是兄弟单词 注意 xff1a bca和abc是兄弟单词 xff0c abc和abc是相同单词
  • 合唱团(牛客)

    题目描述 xff1a 计算最少出列多少位同学 xff0c 使得剩下的同学排成合唱队形 说明 xff1a N位同学站成一排 xff0c 音乐老师要请其中的 N K 位同学出列 xff0c 使得剩下的K位同学排成合唱队形 合唱队形是指这样的一种
  • 字符串排序(牛客)

    题目描述 xff1a 编写一个程序 xff0c 将输入字符串中的字符按如下规则排序 规则 1 xff1a 英文字母从 A 到 Z 排列 xff0c 不区分大小写 如 xff0c 输入 xff1a Type 输出 xff1a epTy 规则
  • 字符串加密(牛客)

    题目描述 xff1a 有一种技巧可以对数据进行加密 xff0c 它使用一个单词作为它的密匙 下面是它的工作原理 xff1a 首先 xff0c 选择一个单词作为密匙 xff0c 如TRAILBLAZERS 如果单词中包含有重复的字母 xff0
  • 统计每个月兔子的总数(牛客)

    题目描述 xff1a 有一只兔子 xff0c 从出生后第3个月起每个月都生一只兔子 xff0c 小兔子长到第三个月后每个月又生一只兔子 xff0c 假如兔子都不死 xff0c 问每个月的兔子总数为多少 xff1f 输入描述 xff1a 输入
  • 购物单(牛客)(01背包+分组背包+有依赖的背包)

    题目描述 xff1a 王强今天很开心 xff0c 公司发给N元的年终奖 王强决定把年终奖用于购物 xff0c 他把想买的物品分为两类 xff1a 主件与附件 xff0c 附件是从属于某个主件的 xff0c 下表就是一些主件与附件的例子 xf
  • gmssl 生成SM2证书、加密、解密、签名、验签

    1 生成SM2密钥对 gmssl ecparam genkey name sm2p256v1 out sm2keypair pem text 2 查看SM2密钥对 gmssl ec in sm2keypair pem text 3 生成自签
  • 求小球落地5次后所经历的路程和第五次反弹的高度(牛客)

    题目描述 xff1a 假设一个球从任意高度自由落下 xff0c 每次落地后反跳回原高度的一半 再落下 求它在第5次落地时 xff0c 共经历多少米 第5次反弹多高 xff1f 最后的误差判断是小数点6位 输入描述 xff1a 输入起始高度
  • 输入一行字符,分别统计出包含英文字符、空格、数字和其他字符的个数(牛客)

    题目描述 xff1a 输入一行字符 xff0c 分别统计出包含英文字母 空格 数字和其它字符的个数 输入描述 xff1a 输入一行字符串 xff0c 可以有空格 1qazxsw23 edcvfr45tgbn hy67uj m ki89ol
  • 字符串合并处理(牛客)

    题目描述 xff1a 按照指定规则对输入的字符串进行处理 详细描述 xff1a 将输入的两个字符串合并 对合并后的字符串进行排序 xff0c 要求为 xff1a 下标为奇数的字符和下标为偶数的字符分别从小到大排序 这里的下标意思是字符在字符
  • 蛇形矩阵(牛客)

    题目描述 xff1a 蛇形矩阵是由1开始的自然数依次排列成的一个矩阵上三角形 输入描述 xff1a 输入正整数N xff08 N不大于100 xff09 5 输出描述 xff1a 输出一个N行的蛇形矩阵 1 3 6 10 15 2 5 9
  • 图片整理(牛客)

    题目描述 xff1a Lily上课时使用字母数字图片教小朋友们学习英语单词 xff0c 每次都需要把这些图片按照大小 xff08 ASCII码值从小到大 xff09 排列收好 请大家给Lily帮忙 xff0c 通过C语言解决 输入描述 xf
  • 单词倒排(牛客)

    题目描述 xff1a 对字符串中的所有单词进行倒排 说明 xff1a 1 构成单词的字符只有26个大写或小写英文字母 xff1b 2 非构成单词的字符均视为单词间隔符 xff1b 3 要求倒排后的单词间隔符以一个空格表示 xff1b 如果原
  • 字符串运用-密码截取(牛客)

    题目描述 xff1a xff08 最大回文序列 xff09 Catcher是MCA国的情报员 xff0c 他工作时发现敌国会用一些对称的密码进行通信 xff0c 比如像这些ABBA xff0c ABA xff0c A xff0c 12332
  • 字符串加解密(牛客)

    题目描述 xff1a 1 对输入的字符串进行加解密 xff0c 并输出 2加密方法为 xff1a 当内容是英文字母时则用该英文字母的后一个字母替换 xff0c 同时字母变换大小写 如字母a时则替换为B xff1b 字母Z时则替换为a xff
  • 表达式求值(牛客)

    题目描述 xff1a 给定一个字符串描述的算术表达式 xff0c 计算出结果值 输入字符串长度不超过100 xff0c 合法的字符包括 43 xff0c 0 9 xff0c 字符串内容的合法性及表达式语法的合法性由做题者检查 本题目只涉及整
  • 02 vue框架内部的各种指令和axios操作的代码详解

    目录 前言 第一个完整的Vue程序 el xff1a 挂载点 和 data xff1a 数据对象 v text指令 v html指令 v on指令 v show指令 v if指令 v bind指令 v for指令 v on指令补充 v mo
  • kill 与killall

    查询命令所属软件包 rpm qf usr bin killall psmisc 22 20 15 el7 x86 64 rpm qf usr bin kill util linux 2 23 2 65 el7 9 1 x86 64 命令参数