watch.c
来自「Linux下进程监控相关源代码」· C语言 代码 · 共 278 行
C
278 行
/* watch -- execute a program repeatedly, displaying output fullscreen *//* $Id *//* Based on the original 1991 'watch' by Tony Rems <rembo@unisoft.com> (with mods and corrections by Francois Pinard). Substantially reworked, new features (differences option, SIGWINCH handling, unlimited command length, long line handling) added Apr 1999 by Mike Coleman <mkc@acm.org>.*/#define VERSION "0.2.0"#include <ctype.h>#include <getopt.h>#include <signal.h>#include <ncurses.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/ioctl.h>#include <time.h>#include <unistd.h>struct option longopts[] = { { "differences", optional_argument, 0, 'd' }, { "help", no_argument, 0, 'h' }, { "interval", required_argument, 0, 'n' }, { "version", no_argument, 0, 'v' }, { 0, 0, 0, 0 } };char usage[] = "Usage: %s [-dhnv] [--differences[=cumulative]] [--help] [--interval=<n>] [--version] <command>\n";static char *progname;int curses_started = 0;int height=24, width=80;int screen_size_changed=0;int first_screen=1;#define min(x,y) ((x) > (y) ? (y) : (x))#define max(x,y) ((x) > (y) ? (x) : (y))voiddo_usage(void){ fprintf(stderr, usage, progname); exit(1);}voiddo_exit(int status) { if (curses_started) endwin(); exit(status);}/* signal handler */voiddie(int notused){ do_exit(0);}voidwinch_handler(int notused){ screen_size_changed = 1;}voidget_terminal_size(){ struct winsize w; if (ioctl(2, TIOCGWINSZ, &w) == 0) { if (w.ws_row > 0) height = w.ws_row; if (w.ws_col > 0) width = w.ws_col; }}intmain(int argc, char *argv[]){ int optc; int option_differences=0, option_differences_cumulative=0, option_help=0, option_version=0; int interval=2; char *command; int command_length=0; /* not including final \0 */ progname = argv[0]; while ((optc = getopt_long(argc, argv, "+d::hn:v", longopts, (int *) 0)) != EOF) { switch (optc) { case 'd': option_differences = 1; if (optarg) option_differences_cumulative = 1; break; case 'h': option_help = 1; break; case 'n': { char *s; interval = strtol(optarg, &s, 10); if (!*optarg || *s) do_usage(); } break; case 'v': option_version = 1; break; default: do_usage(); break; } } if (option_version) { fprintf (stderr, "%s\n", VERSION); if (!option_help) exit(0); } if (option_help) { fprintf(stderr, usage, progname); fputs(" -d, --differences[=cumulative]\thighlight changes between updates\n", stderr); fputs("\t\t(cumulative means highlighting is cumulative)\n", stderr); fputs(" -h, --help\t\t\t\tprint a summary of the options\n", stderr); fputs(" -n, --interval=<seconds>\t\tseconds to wait between updates\n", stderr); fputs(" -v, --version\t\t\t\tprint the version number\n", stderr); exit(0); } if (optind >= argc) do_usage(); command = strdup(argv[optind++]); command_length = strlen(command); for (;optind<argc;optind++) { int s = strlen(argv[optind]); char *endp = &command[command_length]; *endp = ' '; command_length += s + 1; command = realloc(command, command_length+1); strcpy(endp+1, argv[optind]); } get_terminal_size(); /* Catch keyboard interrupts so we can put tty back in a sane state. */ signal(SIGINT, die); signal(SIGTERM, die); signal(SIGHUP, die); signal(SIGWINCH, winch_handler); /* Set up tty for curses use. */ curses_started = 1; initscr(); nonl(); noecho(); cbreak(); while (1) { time_t t = time(NULL); char *ts = ctime(&t); int tsl = strlen(ts); char *header; FILE *p; int x, y; if (screen_size_changed) { get_terminal_size(); resizeterm(height, width); clear(); /* redrawwin(stdscr); */ screen_size_changed = 0; first_screen = 1; } /* left justify interval and command, right justify time, clipping all to fit window width */ asprintf(&header, "Every %ds: %.*s", interval, max(width-1, command_length), command); mvaddstr(0, 0, header); if (strlen(header) > width - tsl - 1) mvaddstr(0, width - tsl - 4, "... "); mvaddstr(0, width - tsl + 1, ts); free(header); if (!(p = popen(command, "r"))) { perror("popen"); do_exit(2); } for (y=2; y<height; y++) { int eolseen = 0, tabpending = 0; for (x=0; x<width; x++) { int c = ' '; int attr = 0; if (!eolseen) { /* if there is a tab pending, just spit spaces until the next stop instead of reading characters */ if (!tabpending) do c = getc(p); while (c != EOF && !isprint(c) && c != '\n' && c != '\t'); if (c == '\n') eolseen = 1; else if (c == '\t') tabpending = 1; if (c == EOF || c == '\n' || c == '\t') c = ' '; if (tabpending && (((x + 1) % 8) == 0)) tabpending = 0; } move(y, x); if (option_differences) { int oldch = inch(); char oldc = oldch & A_CHARTEXT; attr = !first_screen && (c != oldc || (option_differences_cumulative && (oldch & A_ATTRIBUTES))); } if (attr) standout(); addch(c); if (attr) standend(); } } pclose(p); first_screen = 0; refresh(); sleep(interval); } endwin(); return 0;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?