[PATCH v2] bootchartd: add new options to set time, output and temporary directory
Felipe Ortiz via busybox <[email protected]> Thu, 11 Jun 2026 01:17:51 -0400
| Newsgroups | gmane.linux.busybox |
|---|---|
| Message-ID | <[email protected]> |
This patch adds some options for the bootchartd config file: * MEASUREMENT_TIME: time to stop measure * BOOTLOG_TEMP_DIR: path (directory) where bootchartd create the temp dir * BOOTLOG_DEST: file name (including path) used to save the final tarball This is v2 because an initial patch was sent time ago, but this one is in better shape, with some fixes Signed-off-by: Felipe Ortiz <[email protected]> --- init/bootchartd.c | 79 ++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 65 insertions(+), 14 deletions(-) diff --git a/init/bootchartd.c b/init/bootchartd.c index a5447c6ad..3280e631c 100644 --- a/init/bootchartd.c +++ b/init/bootchartd.c @@ -79,6 +79,15 @@ //# Sampling period (in seconds) //SAMPLE_PERIOD=0.2 // +//# Time to measure (approximate, in seconds) +//MEASUREMENT_TIME=60 +// +//# Temporary directory +//BOOTLOG_TEMP_DIR=/tmp +// +//# Tarball for the various boot log files +//BOOTLOG_DEST=/var/log/bootchart.tgz +// //not yet supported: //# tmpfs size //# (32 MB should suffice for ~20 minutes worth of log data, but YMMV) @@ -90,9 +99,6 @@ //# is also required. //PROCESS_ACCOUNTING="no" // -//# Tarball for the various boot log files -//BOOTLOG_DEST=/var/log/bootchart.tgz -// //# Whether to automatically stop logging as the boot process completes. //# The logger will look for known processes that indicate bootup completion //# at a specific runlevel (e.g. gdm-binary, mingetty, etc.). @@ -184,11 +190,14 @@ static int dump_procs(FILE *fp, int look_for_login_process) return found_login_process; } -static char *make_tempdir(void) +static char *make_tempdir(const char *bootlog_temp_dir) { - char template[] = "/tmp/bootchart.XXXXXX"; - char *tempdir = xstrdup(mkdtemp(template)); + const char *directory = "bootchart.XXXXXX"; + char *buf = xasprintf("%s/%s", bootlog_temp_dir, directory); + char *tempdir = mkdtemp(buf); + if (!tempdir) { + free(buf); #ifdef __linux__ /* /tmp is not writable (happens when we are used as init). * Try to mount a tmpfs, then cd and lazily unmount it. @@ -216,14 +225,14 @@ static char *make_tempdir(void) return tempdir; } -static void do_logging(unsigned sample_period_us, int process_accounting) +static void do_logging(unsigned sample_period_us, int process_accounting, int measurement_time) { FILE *proc_stat = xfopen_for_write("proc_stat.log"); FILE *proc_diskstats = xfopen_for_write("proc_diskstats.log"); //FILE *proc_netdev = xfopen_for_write("proc_netdev.log"); FILE *proc_ps = xfopen_for_write("proc_ps.log"); int look_for_login_process = (getppid() == 1); - unsigned count = 60*1000*1000 / sample_period_us; /* ~1 minute */ + unsigned count = (unsigned)measurement_time*1000*1000 / sample_period_us; if (process_accounting) { close(xopen("kernel_pacct", O_WRONLY | O_CREAT | O_TRUNC)); @@ -262,12 +271,13 @@ static void do_logging(unsigned sample_period_us, int process_accounting) } } -static void finalize(char *tempdir, const char *prog, int process_accounting) +static void finalize(char *tempdir, const char *prog, int process_accounting, const char *bootlog_dest) { //# Stop process accounting if configured //local pacct= //[ -e kernel_pacct ] && pacct=kernel_pacct + const char *args[9] = { 0 }; FILE *header_fp = xfopen_for_write("header"); if (process_accounting) @@ -315,7 +325,17 @@ static void finalize(char *tempdir, const char *prog, int process_accounting) fclose(header_fp); /* Package log files */ - system(xasprintf("tar -zcf /var/log/bootlog.tgz header %s *.log", process_accounting ? "kernel_pacct" : "")); + args[0] = "tar"; + args[1] = "-zcf"; + args[2] = bootlog_dest; + args[3] = "header"; + args[4] = "proc_stat.log"; + args[5] = "proc_diskstats.log"; + args[6] = "proc_ps.log"; + args[7] = process_accounting ? "kernel_pacct" : NULL; + + spawn_and_wait((char**)args); + /* Clean up (if we are not in detached tmpfs) */ if (tempdir) { unlink("header"); @@ -345,10 +365,20 @@ static void finalize(char *tempdir, const char *prog, int process_accounting) int bootchartd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int bootchartd_main(int argc UNUSED_PARAM, char **argv) { - unsigned sample_period_us; pid_t parent_pid, logger_pid; smallint cmd; int process_accounting; + + /* config file options */ + unsigned sample_period_us; + int measurement_time; + char bootlog_tempdir[PATH_MAX] = { 0 }; + char bootlog_dest[PATH_MAX] = { 0 }; + + /* Default paths */ + const char *default_bootlog_tempdir = "/tmp"; + const char *default_bootlog_dest = "/var/log/bootchart.tgz"; + enum { CMD_STOP = 0, CMD_START, @@ -383,6 +413,10 @@ int bootchartd_main(int argc UNUSED_PARAM, char **argv) /* Read config file: */ sample_period_us = 200 * 1000; process_accounting = 0; + measurement_time = 60; + memcpy(bootlog_tempdir, default_bootlog_tempdir, strlen(default_bootlog_tempdir)); + memcpy(bootlog_dest, default_bootlog_dest, strlen(default_bootlog_dest)); + if (ENABLE_FEATURE_BOOTCHARTD_CONFIG_FILE) { char* token[2]; parser_t *parser = config_open2("/etc/bootchartd.conf" + 5, fopen_for_read); @@ -396,10 +430,23 @@ int bootchartd_main(int argc UNUSED_PARAM, char **argv) { process_accounting = 1; } + if (strcmp(token[0], "MEASUREMENT_TIME") == 0 && token[1]) + measurement_time = atoi(token[1]); + if (strcmp(token[0], "BOOTLOG_TEMP_DIR") == 0 && token[1]) { + memset(bootlog_tempdir, 0, PATH_MAX); + memcpy(bootlog_tempdir, token[1], strnlen(token[1], PATH_MAX - 1)); + } + if (strcmp(token[0], "BOOTLOG_DEST") == 0 && token[1]) { + memset(bootlog_dest, 0, PATH_MAX); + memcpy(bootlog_dest, token[1], strnlen(token[1], PATH_MAX - 1)); + } } config_close(parser); if ((int)sample_period_us <= 0) sample_period_us = 1; /* prevent division by 0 */ + + if (measurement_time <= 0) + measurement_time = 60; } /* Create logger child: */ @@ -427,9 +474,13 @@ int bootchartd_main(int argc UNUSED_PARAM, char **argv) if (cmd == CMD_PID1 && !getenv("PATH")) putenv((char*)bb_PATH_root_path); - tempdir = make_tempdir(); - do_logging(sample_period_us, process_accounting); - finalize(tempdir, cmd == CMD_START ? argv[2] : NULL, process_accounting); + tempdir = make_tempdir(bootlog_tempdir); + do_logging(sample_period_us, process_accounting, measurement_time); + finalize(tempdir, cmd == CMD_START ? argv[2] : NULL, process_accounting, bootlog_dest); + + if (tempdir) + free(tempdir); + return EXIT_SUCCESS; } -- 2.53.0