#include <errno.h>
#include <fcntl.h>
#include <stdbool.h>
-#include <systemd/sd-journal.h>
+#include "systemd/sd-journal.h"
#include "util.h"
#include "fileio.h"
static int exiting = 0;
int sysfd=-1;
+#define DEFAULT_SAMPLES_LEN 500
+#define DEFAULT_HZ 25.0
+#define DEFAULT_SCALE_X 100.0 /* 100px = 1sec */
+#define DEFAULT_SCALE_Y 20.0 /* 16px = 1 process bar */
+#define DEFAULT_INIT "/sbin/init"
+#define DEFAULT_OUTPUT "/run/log"
+
/* graph defaults */
bool arg_entropy = false;
bool initcall = true;
bool arg_show_cgroup = false;
bool arg_pss = false;
int samples;
-int arg_samples_len = 500; /* we record len+1 (1 start sample) */
-double arg_hz = 25.0; /* 20 seconds log time */
-double arg_scale_x = 100.0; /* 100px = 1sec */
-double arg_scale_y = 20.0; /* 16px = 1 process bar */
+int arg_samples_len = DEFAULT_SAMPLES_LEN; /* we record len+1 (1 start sample) */
+double arg_hz = DEFAULT_HZ;
+double arg_scale_x = DEFAULT_SCALE_X;
+double arg_scale_y = DEFAULT_SCALE_Y;
static struct list_sample_data *sampledata;
struct list_sample_data *head;
-char arg_init_path[PATH_MAX] = "/sbin/init";
-char arg_output_path[PATH_MAX] = "/run/log";
+char arg_init_path[PATH_MAX] = DEFAULT_INIT;
+char arg_output_path[PATH_MAX] = DEFAULT_OUTPUT;
static void signal_handler(int sig) {
if (sig++)
{ "Bootchart", "ControlGroup", config_parse_bool, 0, &arg_show_cgroup },
{ NULL, NULL, NULL, 0, NULL }
};
- _cleanup_fclose_ FILE *f;
- int r;
- f = fopen(BOOTCHART_CONF, "re");
- if (!f)
- return;
-
- r = config_parse(NULL, BOOTCHART_CONF, f,
- NULL, config_item_table_lookup, (void*) items, true, false, NULL);
- if (r < 0)
- log_warning("Failed to parse configuration file: %s", strerror(-r));
+ config_parse(NULL, BOOTCHART_CONF, NULL,
+ NULL,
+ config_item_table_lookup, items,
+ true, false, true, NULL);
if (init != NULL)
strscpy(arg_init_path, sizeof(arg_init_path), init);
strscpy(arg_output_path, sizeof(arg_output_path), output);
}
+static void help(void) {
+ fprintf(stdout,
+ "Usage: %s [OPTIONS]\n\n"
+ "Options:\n"
+ " -r, --rel Record time relative to recording\n"
+ " -f, --freq=FREQ Sample frequency [%g]\n"
+ " -n, --samples=N Stop sampling at [%d] samples\n"
+ " -x, --scale-x=N Scale the graph horizontally [%g] \n"
+ " -y, --scale-y=N Scale the graph vertically [%g] \n"
+ " -p, --pss Enable PSS graph (CPU intensive)\n"
+ " -e, --entropy Enable the entropy_avail graph\n"
+ " -o, --output=PATH Path to output files [%s]\n"
+ " -i, --init=PATH Path to init executable [%s]\n"
+ " -F, --no-filter Disable filtering of unimportant or ephemeral processes\n"
+ " -C, --cmdline Display full command lines with arguments\n"
+ " -c, --control-group Display process control group\n"
+ " -h, --help Display this message\n\n"
+ "See bootchart.conf for more information.\n",
+ program_invocation_short_name,
+ DEFAULT_HZ,
+ DEFAULT_SAMPLES_LEN,
+ DEFAULT_SCALE_X,
+ DEFAULT_SCALE_Y,
+ DEFAULT_OUTPUT,
+ DEFAULT_INIT);
+}
+
static int parse_args(int argc, char *argv[]) {
- static struct option options[] = {
- {"rel", no_argument, NULL, 'r'},
- {"freq", required_argument, NULL, 'f'},
- {"samples", required_argument, NULL, 'n'},
- {"pss", no_argument, NULL, 'p'},
- {"output", required_argument, NULL, 'o'},
- {"init", required_argument, NULL, 'i'},
- {"no-filter", no_argument, NULL, 'F'},
- {"cmdline", no_argument, NULL, 'C'},
- {"control-group", no_argument, NULL, 'c'},
- {"help", no_argument, NULL, 'h'},
- {"scale-x", required_argument, NULL, 'x'},
- {"scale-y", required_argument, NULL, 'y'},
- {"entropy", no_argument, NULL, 'e'},
- {NULL, 0, NULL, 0}
+ static const struct option options[] = {
+ {"rel", no_argument, NULL, 'r'},
+ {"freq", required_argument, NULL, 'f'},
+ {"samples", required_argument, NULL, 'n'},
+ {"pss", no_argument, NULL, 'p'},
+ {"output", required_argument, NULL, 'o'},
+ {"init", required_argument, NULL, 'i'},
+ {"no-filter", no_argument, NULL, 'F'},
+ {"cmdline", no_argument, NULL, 'C'},
+ {"control-group", no_argument, NULL, 'c'},
+ {"help", no_argument, NULL, 'h'},
+ {"scale-x", required_argument, NULL, 'x'},
+ {"scale-y", required_argument, NULL, 'y'},
+ {"entropy", no_argument, NULL, 'e'},
+ {}
};
int c;
arg_entropy = true;
break;
case 'h':
- fprintf(stderr, "Usage: %s [OPTIONS]\n\n", argv[0]);
- fprintf(stderr, "Options:\n");
- fprintf(stderr, " -r, --rel Record time relative to recording\n");
- fprintf(stderr, " -f, --freq=FREQ Sample frequency [%f]\n", arg_hz);
- fprintf(stderr, " -n, --samples=N Stop sampling at [%d] samples\n", arg_samples_len);
- fprintf(stderr, " -x, --scale-x=N Scale the graph horizontally [%f] \n", arg_scale_x);
- fprintf(stderr, " -y, --scale-y=N Scale the graph vertically [%f] \n", arg_scale_y);
- fprintf(stderr, " -p, --pss Enable PSS graph (CPU intensive)\n");
- fprintf(stderr, " -e, --entropy Enable the entropy_avail graph\n");
- fprintf(stderr, " -o, --output=PATH Path to output files [%s]\n", arg_output_path);
- fprintf(stderr, " -i, --init=PATH Path to init executable [%s]\n", arg_init_path);
- fprintf(stderr, " -F, --no-filter Disable filtering of processes from the graph\n");
- fprintf(stderr, " that are of less importance or short-lived\n");
- fprintf(stderr, " -C, --cmdline Display the full command line with arguments\n");
- fprintf(stderr, " of processes, instead of only the process name\n");
- fprintf(stderr, " -c, --control-group Display process control group\n");
- fprintf(stderr, " -h, --help Display this message\n\n");
- fprintf(stderr, "See bootchart.conf for more information.\n");
+ help();
exit (EXIT_SUCCESS);
default:
break;
time_t t = 0;
int r;
struct rlimit rlim;
+ bool has_procfs = false;
parse_conf();
log_uptime();
+ if (graph_start < 0.0) {
+ fprintf(stderr,
+ "Failed to setup graph start time.\n\nThe system uptime "
+ "probably includes time that the system was suspended. "
+ "Use --rel to bypass this issue.\n");
+ exit (EXIT_FAILURE);
+ }
+
+ has_procfs = access("/proc/vmstat", F_OK) == 0;
+
LIST_HEAD_INIT(head);
/* main program loop */
if (sysfd < 0)
sysfd = open("/sys", O_RDONLY|O_CLOEXEC);
- if (!build)
- parse_env_file("/etc/os-release", NEWLINE,
- "PRETTY_NAME", &build,
- NULL);
+ if (!build) {
+ if (parse_env_file("/etc/os-release", NEWLINE, "PRETTY_NAME", &build, NULL) == -ENOENT)
+ parse_env_file("/usr/lib/os-release", NEWLINE, "PRETTY_NAME", &build, NULL);
+ }
- /* wait for /proc to become available, discarding samples */
- if (graph_start <= 0.0)
- log_uptime();
- else
+ if (has_procfs)
log_sample(samples, &sampledata);
+ else
+ /* wait for /proc to become available, discarding samples */
+ has_procfs = access("/proc/vmstat", F_OK) == 0;
sample_stop = gettime_ns();