diff --git a/cmake/modules/cli11.cmake b/cmake/modules/cli11.cmake new file mode 100644 index 0000000000..796200ac7e --- /dev/null +++ b/cmake/modules/cli11.cmake @@ -0,0 +1,12 @@ +option(USE_BUNDLED_CLI11 "Enable building of the bundled CLI11" ${USE_BUNDLED_DEPS}) + +if(USE_BUNDLED_CLI11) + include(FetchContent) + FetchContent_Declare(cli11 + URL https://github.com/CLIUtils/CLI11/archive/refs/tags/v2.4.1.tar.gz + URL_HASH SHA256=73b7ec52261ce8fe980a29df6b4ceb66243bb0b779451dbd3d014cfec9fdbb58 + ) + FetchContent_MakeAvailable(cli11) +else() + find_package(CLI11 CONFIG REQUIRED) +endif() diff --git a/cmake/modules/yaml-cpp.cmake b/cmake/modules/yaml-cpp.cmake index 92a2e9c07a..064dfd77e4 100644 --- a/cmake/modules/yaml-cpp.cmake +++ b/cmake/modules/yaml-cpp.cmake @@ -17,8 +17,9 @@ option(USE_BUNDLED_YAMLCPP "Enable building of the bundled yamlcpp" ${USE_BUNDLE if(USE_BUNDLED_YAMLCPP) include(FetchContent) FetchContent_Declare(yamlcpp - URL https://github.com/jbeder/yaml-cpp/archive/refs/tags/0.8.0.tar.gz - URL_HASH SHA256=fbe74bbdcee21d656715688706da3c8becfd946d92cd44705cc6098bb23b3a16 + GIT_REPOSITORY https://github.com/jbeder/yaml-cpp.git + GIT_TAG yaml-cpp-0.9.0 + GIT_SHALLOW ON ) FetchContent_MakeAvailable(yamlcpp) else() diff --git a/scripts/completions/bash/sysdig b/scripts/completions/bash/sysdig index d0d414df32..da1c322e0d 100644 --- a/scripts/completions/bash/sysdig +++ b/scripts/completions/bash/sysdig @@ -14,24 +14,40 @@ _sysdig_complete() -D \ --debug \ -e \ - --events \ + --event-limit \ -E \ --exclude-users \ -F \ --fatfile \ -G \ --seconds \ + -H \ + --plugin \ + -I \ + --input \ + -i \ + --chisel-info \ -h \ --help \ -j \ --json \ - -k \ - --k8s-api \ -L \ --list-events \ -l \ --list \ - -lv \ + --list-markdown \ + --libs-version \ + --log-level \ + --color \ + --filter-proclist \ + --gvisor-config \ + --gvisor-root \ + --gvisor-generate-config \ + --plugin-config-file \ + --plugin-info \ + --large-environment \ + --unbuffered \ + --version \ --page-faults \ -P \ --progress \ @@ -64,9 +80,7 @@ _sysdig_complete() -t \ --timetype \ -c \ - --chisel \ - -i \ - --chisel-info' + --chisel' local cur=${COMP_WORDS[COMP_CWORD]} local prev=${COMP_WORDS[COMP_CWORD-1]} diff --git a/scripts/completions/zsh/_sysdig b/scripts/completions/zsh/_sysdig index 0270dd95ae..572aafa4d9 100644 --- a/scripts/completions/zsh/_sysdig +++ b/scripts/completions/zsh/_sysdig @@ -214,19 +214,27 @@ _arguments '(-d --displayflt)'{-d,--displayflt}'[Make the given filter a display one]' \ '(-D --debug)'{-D,--debug}'[Capture events about sysdig itself]' \ '(-E --exclude-users)'{-E,--exclude-users}'[Don'\''t create the user/group tables when starting]' \ - '(-e --events)'{-e,--events}'[Rotate the capture file every events]:Maximum event number:' \ + '(-e --event-limit)'{-e,--event-limit}'[Rotate the capture file every events]:Maximum event number:' \ '(-F --fatfile)'{-F,--fatfile}'[Enable fatfile mode]' \ '(-G --seconds)'{-G,--seconds=-}'[Rotate the capture file every seconds]:Rotation period (seconds):' \ + '(-g --gvisor-config)'{-g,--gvisor-config=-}'[Parse events from gVisor using a config file]:Config file:_files' \ + '--gvisor-root=[gVisor root directory]:Root path:_files -/' \ + '--gvisor-generate-config=-[Generate a gVisor configuration file]:Socket path:_files' \ '(-h --help)'{-h,--help}'[Print this help]' \ + '(-H --plugin)'{-H,--plugin=-}'[Register a plugin with optional init config]:Plugin spec:' \ + '(-I --input)'{-I,--input=-}'[Select a plugin as input source]:Plugin input spec:' \ '(-j --json)'{-j,--json}'[Emit output as JSON]' \ - '(-k --k8s-api)'{-k,--k8s-api}'[Kubernetes API server]' \ '(-L --list-events)'{-L,--list-events}'[List the events that the engine supports]' \ - '(-l -lv --list)'{-l,--list}'[List the fields that can be used for filtering]' \ - '(-l -lv --list)-lv[Verbosely list the fields that can be used for filtering]' \ + '(-l --list)'{-l,--list}'[List the fields that can be used for filtering]:Field source:' \ + '--list-markdown=[List the fields in markdown format]:Field source:' \ + '--libs-version[Print the falcosecurity/libs version]' \ + '--log-level=[Select log level]:Log level:(trace debug info notice warning error critical fatal)' \ '(-n --numevents)'{-n,--numevents=-}'[Stop capturing after events]:Max events:' \ '--page-faults[Capture user/kernel major/minor page faults]' \ '(-P --progress)'{-P,--progress}'[Print progress on stderr while processing trace files]' \ '(-p --print)'{-p,--print=-}'[Specify the event format (default reported with "sysdig -pp")]:Event output format:->format' \ + '--plugin-config-file=[Load plugin configuration from file]:Config file:_files' \ + '--plugin-info=[Print info for a single plugin]:Plugin name:' \ '(-q --quiet)'{-q,--quiet}'[Do not print events on the screen]' \ '(-r --read)'{-r,--read=-}'[Read events from ]:Input file:_files -g "*.scap"' \ '(-R --resolve-ports)'{-R,--resolve-ports}'[Resolve port numbers to names.]' \ @@ -239,7 +247,11 @@ _arguments d\:"delta between enter/exit" \ D\:"delta from previous event"))' \ '(-v --verbose)'{-v,--verbose}'[Verbose output]' \ + '--color=[Set color mode]:Color mode:(true false force)' \ + '--filter-proclist[Apply filter to /proc dump when reading from a file]' \ + '--large-environment[Support environments larger than 4KiB]' \ '--unbuffered[Disable buffering of output]' \ + '--version[Print version number]' \ '(-w --write)'{-w,--write=-}'[Write events to ]:Output file:_files -g "*.scap"' \ '(-W --limit)'{-W,--limit}'[Limit split captures (-C, -G or -e) to a given number of files]:Max # of files' \ '(-x --print-hex)'{-x,--print-hex}'[Print data buffers in hex]' \ diff --git a/userspace/sysdig/CMakeLists.txt b/userspace/sysdig/CMakeLists.txt index 4acbb0300c..07b166530f 100644 --- a/userspace/sysdig/CMakeLists.txt +++ b/userspace/sysdig/CMakeLists.txt @@ -22,6 +22,7 @@ endif() # NOT WIN32 include(zlib) include(luajit) +include(cli11) include_directories("${PROJECT_BINARY_DIR}/userspace/sinspui") include_directories(../sinspui) @@ -36,12 +37,10 @@ if(NOT WIN32) csysdig.cpp) else() set(SOURCE_FILES - sysdig.cpp - win32/getopt.c) + sysdig.cpp) set(SOURCE_FILES_CSYSDIG - csysdig.cpp - win32/getopt.c) + csysdig.cpp) endif() list(APPEND SOURCE_FILES @@ -86,6 +85,7 @@ if(USE_BUNDLED_DEPS) add_dependencies(csysdig yaml-cpp) add_dependencies(sysdig luajit) add_dependencies(csysdig luajit) + # CLI11 is header-only, no build dependency needed endif() if(USE_BUNDLED_FALCOSECURITY_LIBS) @@ -118,7 +118,8 @@ if(NOT WIN32) target_link_libraries(sysdig "${SINSP_LIB}" "${LUAJIT_LIB}" - yaml-cpp) + yaml-cpp + CLI11::CLI11) if(USE_BUNDLED_NCURSES) add_dependencies(csysdig ncurses) @@ -128,7 +129,8 @@ if(NOT WIN32) "${SINSP_LIB}" "${LUAJIT_LIB}" "${CURSES_LIBRARIES}" - yaml-cpp) + yaml-cpp + CLI11::CLI11) add_subdirectory(man) @@ -150,12 +152,14 @@ else() target_link_libraries(sysdig "${SINSP_LIB}" "${LUAJIT_LIB}" - yaml-cpp) + yaml-cpp + CLI11::CLI11) target_link_libraries(csysdig "${SINSP_LIB}" "${LUAJIT_LIB}" - yaml-cpp) + yaml-cpp + CLI11::CLI11) target_link_libraries(sysdig odbc32.lib odbccp32.lib Netapi32.lib Iphlpapi.lib) diff --git a/userspace/sysdig/csysdig.cpp b/userspace/sysdig/csysdig.cpp index 2a098c9e06..6364e7f839 100644 --- a/userspace/sysdig/csysdig.cpp +++ b/userspace/sysdig/csysdig.cpp @@ -26,6 +26,7 @@ limitations under the License. #include #include #include +#include #include #include "plugin_manager.h" @@ -46,12 +47,12 @@ limitations under the License. #include "utils/supported_fields.h" #include "filterchecks/sinsp_filtercheck_syslog.h" +#include + #ifdef _WIN32 -#include "win32/getopt.h" #include #else #include -#include #include #endif @@ -68,6 +69,98 @@ static bool g_terminate = false; static bool g_plugin_input = false; static void usage(); +// +// Command-line options structure (for CLI11 refactoring) +// +struct csysdig_options { + // Common options + bool help = false; + bool version = false; + bool exclude_users = false; + bool resolve_ports = false; + bool list_fields = false; + bool list_views = false; + + // Display format options + bool print_ascii = false; + bool print_hex_ascii = false; + bool print_containers = false; + bool json = false; + bool raw = false; + bool interactive = false; + + // Capture options + std::string bpf_probe; + bool modern_bpf = false; + int cpus_for_each_buffer = 0; + bool page_faults = false; + bool large_environment = false; + + // I/O options + std::vector read_files; + int snaplen = 0; + uint64_t num_events = std::numeric_limits::max(); + + // UI options + uint64_t refresh_interval_ms = 2000; // Default 2 seconds + std::string view_id; + std::string logfile; + bool force_term_compat = false; + int32_t json_first_row = 0; + int32_t json_last_row = 0; + int32_t sorting_col = -1; + + // Remaining positional args (filter) + std::vector filter_args; +}; + +static bool is_short_option_with_value_csysdig(const std::string& arg, const std::string& opts) +{ + return arg.size() > 2 && arg[0] == '-' && arg[1] != '-' && opts.find(arg[1]) != std::string::npos; +} + +static std::vector normalize_csysdig_argv(int argc, char** argv) +{ + std::vector normalized; + normalized.reserve(argc); + if(argc > 0) + { + normalized.emplace_back(argv[0]); + } + + for(int i = 1; i < argc; ++i) + { + std::string arg = argv[i]; + if(is_short_option_with_value_csysdig(arg, "Bdnprsv")) + { + normalized.emplace_back(arg.substr(0, 2)); + normalized.emplace_back(arg.substr(2)); + continue; + } + + normalized.emplace_back(std::move(arg)); + } + + return normalized; +} + +static std::vector argv_ptrs_csysdig(std::vector& args) +{ + std::vector res; + res.reserve(args.size()); + for(auto& arg : args) + { + res.push_back(arg.data()); + } + return res; +} + +static int count_enabled_formats(const csysdig_options& opts) +{ + return (opts.print_ascii ? 1 : 0) + + (opts.print_hex_ascii ? 1 : 0); +} + // // Helper functions // @@ -345,18 +438,122 @@ captureinfo do_inspect(sinsp* inspector, std::string g_version_string = SYSDIG_VERSION; +// +// CLI11-based argument parser for csysdig +// +csysdig_options parse_args_cli11_csysdig(int argc, char **argv) +{ + csysdig_options opts; + + CLI::App app{"csysdig - the ncurses user interface for sysdig\n" + "csysdig version " SYSDIG_VERSION}; + + // Disable help flag so we can handle it ourselves for backwards compatibility + app.set_help_flag(""); + app.allow_extras(); // Allow extra arguments for filter + + // Common options + app.add_flag("-h,--help", opts.help, "Print this help message"); + app.add_flag("--version", opts.version, "Print version number"); + app.add_flag("-E,--exclude-users", opts.exclude_users, "Don't create user/group tables"); + app.add_flag("-R,--resolve-ports", opts.resolve_ports, "Resolve port numbers to names"); + app.add_flag("-l,--list", opts.list_fields, "List all fields that can be used in views"); + app.add_flag("--list-views", opts.list_views, "List available views"); + + // Display format options + app.add_flag("-A,--print-ascii", opts.print_ascii, + "When emitting JSON, print only text portion of data buffers"); + app.add_flag("-X,--print-hex-ascii", opts.print_hex_ascii, + "When emitting JSON, print data buffers in hex and ASCII"); + + app.add_flag("-j,--json", opts.json, "Enable JSON output"); + app.add_flag("--raw", opts.raw, "Print raw output instead of ncurses"); + app.add_flag("--interactive", opts.interactive, "Enable interactive mode"); + + auto print_opt = app.add_option("-p,--print", "Print format (c/container for container-friendly format)"); + print_opt->each([&opts](const std::string& val) { + if(val == "c" || val == "container") { + opts.print_containers = true; + } + }); + + // Capture options + app.add_option("-B,--bpf", opts.bpf_probe, + "Enable live capture using BPF probe") + ->expected(0, 1) + ->type_name("PROBE"); + +#ifdef HAS_MODERN_BPF + app.add_flag("--modern-bpf", opts.modern_bpf, + "Enable live capture using modern BPF probe"); + app.add_option("--cpus-for-each-buffer", opts.cpus_for_each_buffer, + "CPUs per syscall buffer (modern BPF only)") + ->type_name("NUM"); +#endif + + app.add_flag("--page-faults", opts.page_faults, "Capture user/kernel page faults"); + app.add_flag("--large-environment", opts.large_environment, + "Support environments larger than 4KiB"); + + // I/O options + app.add_option("-r,--read,--readfile", opts.read_files, "Read events from file") + ->type_name("FILE") + ->check(CLI::ExistingFile); + + app.add_option("-s,--snaplen", opts.snaplen, "Capture first bytes of I/O buffers") + ->type_name("LEN"); + + app.add_option("-n,--numevents", opts.num_events, "Stop capturing after events") + ->type_name("NUM"); + + // UI options + app.add_option("-d,--delay", opts.refresh_interval_ms, + "Set delay between updates in milliseconds") + ->type_name("MS") + ->check(CLI::Range(100, 3600000)); // 100ms to 1 hour + + app.add_option("-v,--view", opts.view_id, + "Run the view with the given ID when csysdig starts") + ->type_name("VIEW_ID"); + + app.add_option("--logfile", opts.logfile, "Print program logs into the given file") + ->type_name("FILE"); + + app.add_flag("--force-term-compat", opts.force_term_compat, + "Try to configure simple terminal settings for better compatibility"); + + app.add_option("--from", opts.json_first_row, "First row for JSON output") + ->type_name("ROW"); + + app.add_option("--to", opts.json_last_row, "Last row for JSON output") + ->type_name("ROW"); + + app.add_option("--sortingcol", opts.sorting_col, "Sorting column number") + ->type_name("COL"); + + try { + app.parse(argc, argv); + + // Collect remaining arguments as filter + opts.filter_args = app.remaining(); + + } catch(const CLI::ParseError &e) { + throw sinsp_exception(e.what()); + } + + return opts; +} + sysdig_init_res csysdig_init(int argc, char **argv) { sysdig_init_res res; sinsp* inspector = NULL; std::vector infiles; - int op; uint64_t cnt = -1; uint32_t snaplen = 0; - int long_index = 0; - int32_t n_filterargs = 0; captureinfo cinfo; std::string errorstr; + std::string filter; std::string display_view; bool print_containers = false; uint64_t refresh_interval_ns = 2000000000; @@ -377,51 +574,18 @@ sysdig_init_res csysdig_init(int argc, char **argv) bool force_term_compat = false; sinsp_evt::param_fmt event_buffer_format = sinsp_evt::PF_NORMAL; plugin_utils plugins; - bool list_plugins = false; sinsp_opener opener; std::shared_ptr filter_list; - static struct option long_options[] = - { - {"print-ascii", no_argument, 0, 'A' }, - {"bpf", optional_argument, 0, 'B' }, -#ifdef HAS_MODERN_BPF - {"cpus-for-each-buffer", required_argument, 0, 0 }, -#endif - {"delay", required_argument, 0, 'd' }, - {"exclude-users", no_argument, 0, 'E' }, - {"from", required_argument, 0, 0 }, - {"help", no_argument, 0, 'h' }, - {"json", no_argument, 0, 'j' }, - {"interactive", optional_argument, 0, 0 }, - {"large-environment", no_argument, 0, 0 }, - {"list", optional_argument, 0, 'l' }, - {"list-views", no_argument, 0, 0}, -#ifdef HAS_MODERN_BPF - {"modern-bpf", no_argument, 0, 0 }, -#endif - {"numevents", required_argument, 0, 'n' }, - {"page-faults", no_argument, 0, 0 }, - {"print", required_argument, 0, 'p' }, - {"resolve-ports", no_argument, 0, 'R'}, - {"readfile", required_argument, 0, 'r' }, - {"raw", no_argument, 0, 0 }, - {"snaplen", required_argument, 0, 's' }, - {"logfile", required_argument, 0, 0 }, - {"force-term-compat", no_argument, 0, 0}, - {"sortingcol", required_argument, 0, 0 }, - {"to", required_argument, 0, 0 }, - {"view", required_argument, 0, 'v' }, - {"version", no_argument, 0, 0 }, - {"print-hex-ascii", no_argument, 0, 'X'}, - {0, 0, 0, 0} - }; - // // Parse the arguments // try { + auto normalized_args = normalize_csysdig_argv(argc, argv); + auto normalized_argv = argv_ptrs_csysdig(normalized_args); + auto opts = parse_args_cli11_csysdig((int)normalized_argv.size(), normalized_argv.data()); + inspector = new sinsp(); #ifdef HAS_CHISELS @@ -433,229 +597,150 @@ sysdig_init_res csysdig_init(int argc, char **argv) // Load container plugin (if available) plugins.load_container_plugin_if_available(inspector); - // - // Parse the args - // - while((op = getopt_long(argc, argv, - "AB::d:Ehk:K:jlm:n:p:Rr:s:v:X", long_options, &long_index)) != -1) + if(count_enabled_formats(opts) > 1) { - switch(op) + fprintf(stderr, "you cannot specify more than one output format\n"); + delete inspector; + return sysdig_init_res(EXIT_FAILURE); + } + + if(opts.help) + { + usage(); + delete inspector; + return sysdig_init_res(EXIT_SUCCESS); + } + + if(opts.version) + { + printf("sysdig version %s\n", SYSDIG_VERSION); + delete inspector; + return sysdig_init_res(EXIT_SUCCESS); + } + + if(opts.print_ascii) + { + event_buffer_format = sinsp_evt::PF_EOLS_COMPACT; + } + else if(opts.print_hex_ascii) + { + event_buffer_format = sinsp_evt::PF_HEXASCII; + } + + if(!opts.bpf_probe.empty() || std::find(normalized_args.begin(), normalized_args.end(), "-B") != normalized_args.end()) + { + opener.bpf.enabled = true; + opener.bpf.probe = opts.bpf_probe; + } + + if(opts.refresh_interval_ms != 2000) + { + refresh_interval_ns = opts.refresh_interval_ms * 1000000; + if(refresh_interval_ns < 100000000) { - case '?': - // - // Command line error - // - throw sinsp_exception("command line error"); - break; - case 'A': - if(event_buffer_format != sinsp_evt::PF_NORMAL) - { - fprintf(stderr, "you cannot specify more than one output format\n"); - delete inspector; - return sysdig_init_res(EXIT_SUCCESS); - } + throw sinsp_exception("Period must be bigger then 100ms"); + } + } - event_buffer_format = sinsp_evt::PF_EOLS_COMPACT; - break; - case 'B': + if(opts.exclude_users) + { + inspector->set_import_users(false); + } + + if(opts.json) + { + output_type = chisel_table::OT_JSON; + } + + list_flds = opts.list_fields; + + if(opts.num_events != std::numeric_limits::max()) + { + if(opts.num_events == 0) { - opener.bpf.enabled = true; - if(optarg) - { - opener.bpf.probe = optarg; - } - break; + throw sinsp_exception("invalid event count 0"); } - case 'd': - try - { - refresh_interval_ns = sinsp_numparser::parseu64(optarg) * 1000000; - } - catch(...) - { - throw sinsp_exception("can't parse the -d argument, make sure it's a number"); - } + cnt = opts.num_events; + } - if(refresh_interval_ns < 100000000) - { - throw sinsp_exception("Period must be bigger then 100ms"); - } + print_containers = opts.print_containers; - break; - case 'E': - inspector->set_import_users(false); - break; - case 'h': - usage(); - delete inspector; - return sysdig_init_res(EXIT_SUCCESS); - case 'j': - output_type = chisel_table::OT_JSON; - break; - case 'l': - list_flds = true; - break; - case 'n': - try - { - cnt = sinsp_numparser::parseu64(optarg); - } - catch(...) - { - throw sinsp_exception("can't parse the -n argument, make sure it's a number"); - } + if(opts.resolve_ports) + { + inspector->set_hostname_and_port_resolution_mode(true); + } - if(cnt <= 0) - { - throw sinsp_exception(std::string("invalid event count ") + optarg); - res.m_res = EXIT_FAILURE; - goto exit; - } - break; - case 'p': - if(std::string(optarg) == "c" || std::string(optarg) == "container") - { - print_containers = true; - } + infiles = opts.read_files; + snaplen = (uint32_t)opts.snaplen; + display_view = opts.view_id; - break; - case 'R': - inspector->set_hostname_and_port_resolution_mode(true); - break; - case 'r': - infiles.push_back(optarg); - break; - case 's': - snaplen = atoi(optarg); - break; - case 'v': - display_view = optarg; - break; - case 'X': - if(event_buffer_format != sinsp_evt::PF_NORMAL) - { - fprintf(stderr, "you cannot specify more than one output format\n"); - delete inspector; - return sysdig_init_res(EXIT_FAILURE); - } + if(opts.interactive) + { + is_interactive = true; + output_type = chisel_table::OT_JSON; + } - event_buffer_format = sinsp_evt::PF_HEXASCII; - break; - case 0: - { - if(long_options[long_index].flag != 0) - { - break; - } + if(opts.large_environment) + { + inspector->set_large_envs(true); + } - std::string optname = std::string(long_options[long_index].name); - if(optname == "version") - { - printf("sysdig version %s\n", SYSDIG_VERSION); - delete inspector; - return sysdig_init_res(EXIT_SUCCESS); - } - else if(optname == "interactive") - { - is_interactive = true; - output_type = chisel_table::OT_JSON; - } - else if(optname == "large-environment") - { - inspector->set_large_envs(true); - } -#ifdef HAS_MODERN_BPF - else if(optname == "cpus-for-each-buffer") - { - opener.bpf.cpus_for_each_syscall_buffer = sinsp_numparser::parsed16(optarg); - } -#endif - else if(optname == "logfile") - { - inspector->set_log_file(optarg); - } - else if(optname == "raw") - { - output_type = chisel_table::OT_RAW; - } - else if(optname == "force-term-compat") - { - force_term_compat = true; - } - else if(optname == "from") - { - json_first_row = sinsp_numparser::parsed32(optarg); - } #ifdef HAS_MODERN_BPF - else if(optname == "modern-bpf") - { - opener.bpf.enabled = true; - opener.bpf.modern = true; - } + if(opts.cpus_for_each_buffer != 0) + { + opener.bpf.cpus_for_each_syscall_buffer = (uint16_t)opts.cpus_for_each_buffer; + } + if(opts.modern_bpf) + { + opener.bpf.enabled = true; + opener.bpf.modern = true; + } #endif - else if(optname == "to") - { - json_last_row = sinsp_numparser::parsed32(optarg); - } - else if(optname == "sortingcol") - { - sorting_col = sinsp_numparser::parsed32(optarg); - } - else if(optname == "list-views") - { - list_views = true; - } - else if(optname == "page-faults") - { - opener.options.page_faults = true; - } - } - break; - default: - break; - } + + if(!opts.logfile.empty()) + { + inspector->set_log_file(opts.logfile.c_str()); } - if (list_plugins) + if(opts.raw) { - plugins.print_plugin_info_list(inspector); - printf("More detailed info about individual plugins can be printed with the --plugin-info option:\n"); - printf(" Detailed info about a single plugin\n"); - printf(" $ sysdig --plugin-info=dummy\n\n"); - printf(" Detailed info about a single plugin with a given configuration\n"); - printf(" $ sysdig -H dummy:'{\"jitter\":50}' --plugin-info=dummy\n\n"); - delete inspector; - return sysdig_init_res(EXIT_SUCCESS); + output_type = chisel_table::OT_RAW; } - std::string filter; + force_term_compat = opts.force_term_compat; + json_first_row = opts.json_first_row; + json_last_row = opts.json_last_row; + sorting_col = opts.sorting_col; + list_views = opts.list_views; - // - // If -l was specified, print the fields and exit - // - if(list_flds) + if(opts.page_faults) { - // todo(jasondellaluce): support source selection, verbosity, markdown - print_supported_fields(inspector, plugins, "", true, false); - res.m_res = EXIT_SUCCESS; - goto exit; + opener.options.page_faults = true; } - // - // the filter is at the end of the command line - // - if(optind + n_filterargs < argc) + if(!opts.filter_args.empty()) { - for(int32_t j = optind + n_filterargs; j < argc; j++) + for(size_t j = 0; j < opts.filter_args.size(); j++) { - filter += argv[j]; - if(j < argc) + filter += opts.filter_args[j]; + if(j + 1 < opts.filter_args.size()) { filter += " "; } } } + // + // If -l was specified, print the fields and exit + // + if(list_flds) + { + // todo(jasondellaluce): support source selection, verbosity, markdown + print_supported_fields(inspector, plugins, "", true, false); + res.m_res = EXIT_SUCCESS; + goto exit; + } + // TODO(therealbobo): add plugins filterchecks filter_list = std::make_shared(); filter_list->add_filter_check(std::make_unique(syslog_decoder)); diff --git a/userspace/sysdig/man/csysdig.8 b/userspace/sysdig/man/csysdig.8 index 69fcd543f0..e6fe1c7f40 100644 --- a/userspace/sysdig/man/csysdig.8 +++ b/userspace/sysdig/man/csysdig.8 @@ -1,32 +1,14 @@ -.\" Automatically generated by Pandoc 2.18 +.\" Automatically generated by Pandoc 3.5 .\" -.\" Define V font for inline verbatim, using C font in formats -.\" that render this, and otherwise B font. -.ie "\f[CB]x\f[]"x" \{\ -. ftr V B -. ftr VI BI -. ftr VB B -. ftr VBI BI -.\} -.el \{\ -. ftr V CR -. ftr VI CI -. ftr VB CB -. ftr VBI CBI -.\} -.TH "" "" "" "" "" -.hy +.TH "" "" "" "" .SS NAME -.PP -csysdig - the ncurses user interface for sysdig +csysdig \- the ncurses user interface for sysdig .SS SYNOPSIS -.PP \f[B]csysdig\f[R] [\f[I]option\f[R]]... [\f[I]filter\f[R]] .SS DESCRIPTION -.PP csysdig exports sysdig\[aq]s functionality through an intuitive and -powerful ncurses-based user interface. +powerful ncurses\-based user interface. .PP csysdig has been designed to mimic tools like \f[B]top\f[R] and \f[B]htop\f[R], but it offers richer functionality, including: @@ -64,12 +46,11 @@ include any sysdig filter field. Views are located in the sysdig chisel directory path, usually \f[I]/usr/share/sysdig/chisels\f[R] and \f[I]\[ti]/.chisels\f[R]. .SS BASIC USAGE -.PP Here are some basic tips to get you started with sysdig: .IP "1." 3 If you run csysdig without arguments, it will display live system data, updating every 2 seconds. -To analyze a trace file, use the -r command line flag. +To analyze a trace file, use the \-r command line flag. .IP "2." 3 You can switch to a different view by using the \f[I]F2\f[R] key. .IP "3." 3 @@ -82,7 +63,6 @@ You can observe input/output for the currently selected entity by typing You can see sysdig events for the currently selected entity by typing \f[I]F6\f[R] .SS DRILLING DOWN -.PP You drill down by selecting an element in a view and then clicking \f[I]enter\f[R]. Once inside a selection, you can switch to a different view, and the new @@ -96,7 +76,6 @@ For example, you can click on a container in the \f[I]Containers\f[R] view to get the processes running inside it, and then click on one of the processes to see its threads. .SS ACTIONS AND HOTKEYS -.PP Each view has a list of command lines that can be executed in the context of the current selection by pressing \[aq]hotkeys\[aq]. For example, pressing \[aq]k\[aq] in the Processes view kills the @@ -108,16 +87,14 @@ You can see which actions a view supports by pressing F8. You can customize the view\[aq]s actions by editing the view\[aq]s Lua file. .SS CONTAINERS SUPPORT -.PP -Starting csysdig with the -pc command line switch will cause many of the -views to include additional container information. +Starting csysdig with the \-pc command line switch will cause many of +the views to include additional container information. For example, the \f[I]Processes\f[R] will include a column showing the container the process belongs to. Similarly, the \f[I]Connections\f[R] view will show which container each connection belongs to. .SS INTERACTIVE COMMANDS .SS Views Window -.PP \f[B]Arrows, PgUP, PgDn, Home, End\f[R] .PD 0 .P @@ -210,11 +187,11 @@ content. .PD Pause screen updates. .PP -\f[B]\f[VB] <1-9>\f[B]\f[R] +\f[B]\f[CB] <1\-9>\f[B]\f[R] .PD 0 .P .PD -sort column \f[V]\f[R] +sort column \f[CR]\f[R] .PP \f[B]F1, h, ?\f[R] .PD 0 @@ -222,7 +199,6 @@ sort column \f[V]\f[R] .PD Show the help screen. .SS Echo and sysdig Windows -.PP \f[B]Arrows, PgUP, PgDn, Home, End\f[R] .PD 0 .P @@ -252,9 +228,9 @@ Find Next. .P .PD Chose the output rendering format. -Options are \[aq]Dotted ASCII\[aq] (non-printable binary bytes are -rendered as dots), \[aq]Printable ASCII\[aq] (non-printable binary bytes -are not included and line endings are rendered accurately) and +Options are \[aq]Dotted ASCII\[aq] (non\-printable binary bytes are +rendered as dots), \[aq]Printable ASCII\[aq] (non\-printable binary +bytes are not included and line endings are rendered accurately) and \[aq]Hex\[aq] (dotted ASCII representation is included together with the Hexadecimal rendering of the buffers). .PP @@ -276,7 +252,6 @@ Pause screen updates. .PD Go to line. .SS Spectrogram Window -.PP \f[B]F2\f[R] .PD 0 .P @@ -308,126 +283,108 @@ view content. You can use the mouse on the entries in the menu at the bottom of the screen to perform their respective actions. .SS COMMAND LINE OPTIONS +\f[B]\-A\f[R], \f[B]\-\-print\-ascii\f[R] When emitting JSON, only print +the text portion of data buffers and preserve line endings. .PP -\f[B]-d\f[R] \f[I]period\f[R], \f[B]--delay\f[R]=\f[I]period\f[R] +\f[B]\-B\f[R][\f[I]bpf_probe\f[R]], +\f[B]\-\-bpf\f[R][=\f[I]bpf_probe\f[R]] Enable live capture using the +specified BPF probe instead of the kernel module. +If no probe path is provided, csysdig will try to load one +automatically. +.PP +\f[B]\-d\f[R] \f[I]period\f[R], \f[B]\-\-delay\f[R]=\f[I]period\f[R] .PD 0 .P .PD Set the delay between updates, in milliseconds (by default = 2000). -This works similarly to the -d option in top. +This works similarly to the \-d option in top. .PP -\f[B]-E\f[R], \f[B]--exclude-users\f[R] +\f[B]\-E\f[R], \f[B]\-\-exclude\-users\f[R] .PD 0 .P .PD Don\[aq]t create the user/group tables by querying the OS when sysdig starts. This also means that no user or group info will be written to the -tracefile by the -w flag. +tracefile by the \-w flag. The user/group tables are necessary to use filter fields like user.name or group.name. However, creating them can increase sysdig\[aq]s startup time. .PP -\f[B]--force-term-compat\f[R] +\f[B]\-\-force\-term\-compat\f[R] .PD 0 .P .PD -Try to configure simple terminal settings (xterm-1002) that work better +Try to configure simple terminal settings (xterm\-1002) that work better with terminals like putty. Try to use this flag if you experience terminal issues like the mouse not working. .PP -\f[B]-h\f[R], \f[B]--help\f[R] +\f[B]\-h\f[R], \f[B]\-\-help\f[R] .PD 0 .P .PD Print this page .PP -\f[B]-k\f[R], \f[B]--k8s-api\f[R] Enable Kubernetes support by -connecting to the API server specified as argument. -E.g. -\[dq]\[dq]. -The API server can also be specified via the environment variable -SYSDIG_K8S_API. -.PP -\f[B]-K\f[R] \f[I]btfile | -certfile:keyfile[#password][:cacertfile]\f[R], -\f[B]--k8s-api-cert=\f[R]_btfile | -certfile:keyfile[#password][:cacertfile]_ Use the provided files names -to authenticate user and (optionally) verify the K8S API server -identity. -Each entry must specify full (absolute, or relative to the current -directory) path to the respective file. -Private key password is optional (needed only if key is password -protected). -CA certificate is optional. -For all files, only PEM file format is supported. -Specifying CA certificate only is obsoleted - when single entry is -provided for this option, it will be interpreted as the name of a file -containing bearer token. -Note that the format of this command-line option prohibits use of files -whose names contain \[aq]:\[aq] or \[aq]#\[aq] characters in the file -name. -Option can also be provided via the environment variable -SYSDIG_K8S_API_CERT. -.PP -\f[B]-l\f[R], \f[B]--list\f[R] +\f[B]\-\-interactive\f[R] Enable interactive JSON mode. +csysdig prints \f[CR]ready\f[R] once initialization completes and then +accepts UI commands on stdin. +.PP +\f[B]\-j\f[R], \f[B]\-\-json\f[R] Emit JSON output instead of the curses +interface. +.PP +\f[B]\-l\f[R], \f[B]\-\-list\f[R] .PD 0 .P .PD List all the fields that can be used in views. .PP -\f[B]--logfile\f[R] \f[I]file\f[R] +\f[B]\-\-list\-views\f[R] List the available csysdig views and exit. +.PP +\f[B]\-\-large\-environment\f[R] Support environments larger than 4KiB +by reading the full environment from \f[CR]/proc\f[R] when needed. +.PP +\f[B]\-\-logfile\f[R] \f[I]file\f[R] .PD 0 .P .PD Print program logs into the given file. .PP -\f[B]-m\f[R] \f[I]url[,marathon-url]\f[R], -\f[B]--mesos-api=\f[R]_url[,marathon-url]_ Enable Mesos support by -connecting to the API server specified as argument (e.g. -). -Mesos url is required. -Marathon url is optional, defaulting to auto-follow - if Marathon API -server is not provided, csysdig will attempt to retrieve (and -subsequently follow, if it migrates) the location of Marathon API server -from the Mesos master. -Note that, with auto-follow, csysdig will likely receive a cluster -internal IP address for Marathon API server, so running csysdig with -Marathon auto-follow from a node that is not part of Mesos cluster may -not work. -Additionally, running csysdig with Mesos support on a node that has no -containers managed by Mesos is of limited use because, although cluster -metadata will be collected, there will be no Mesos/Marathon filtering -capability. -The API servers can also be specified via the environment variable -SYSDIG_MESOS_API. -.PP -\f[B]-n\f[R] \f[I]num\f[R], \f[B]--numevents\f[R]=\f[I]num\f[R] +\f[B]\-n\f[R] \f[I]num\f[R], \f[B]\-\-numevents\f[R]=\f[I]num\f[R] .PD 0 .P .PD Stop capturing after \f[I]num\f[R] events .PP -\f[B]--page-faults\f[R] Capture user/kernel major/minor page faults +\f[B]\-\-page\-faults\f[R] Capture user/kernel major/minor page faults +.PP +\f[B]\-\-modern\-bpf\f[R] Enable live capture using the modern BPF probe +instead of the kernel module. .PP -\f[B]-pc\f[R], \f[B]-pcontainers\f[R]_ +\f[B]\-\-cpus\-for\-each\-buffer\f[R] \f[I]num\f[R] Set how many CPUs +are assigned to each syscall buffer when using the modern BPF probe. +.PP +\f[B]\-pc\f[R], \f[B]\-pcontainers\f[R]_ .PD 0 .P .PD -Instruct csysdig to use a container-friendly format in its views. +Instruct csysdig to use a container\-friendly format in its views. This will cause several of the views to contain additional -container-related columns. +container\-related columns. .PP -\f[B]-R\f[R], \f[B]--resolve-ports\f[R] Resolve port numbers to names. +\f[B]\-R\f[R], \f[B]\-\-resolve\-ports\f[R] Resolve port numbers to +names. .PP -\f[B]-r\f[R] \f[I]readfile\f[R], \f[B]--read\f[R]=\f[I]readfile\f[R] +\f[B]\-r\f[R] \f[I]readfile\f[R], \f[B]\-\-read\f[R]=\f[I]readfile\f[R] .PD 0 .P .PD Read the events from \f[I]readfile\f[R]. .PP -\f[B]-s\f[R] \f[I]len\f[R], \f[B]--snaplen\f[R]=\f[I]len\f[R] +\f[B]\-\-raw\f[R] Print raw output to a regular terminal instead of +enabling the curses interface. +.PP +\f[B]\-s\f[R] \f[I]len\f[R], \f[B]\-\-snaplen\f[R]=\f[I]len\f[R] .PD 0 .P .PD @@ -435,47 +392,44 @@ Capture the first \f[I]len\f[R] bytes of each I/O buffer. By default, the first 80 bytes are captured. Use this option with caution, it can generate huge trace files. .PP -\f[B]-T\f[R], \f[B]--force-tracers-capture\f[R] -.PD 0 -.P -.PD -Tell the driver to make sure full buffers are captured from /dev/null, -to make sure that tracers are completely captured. -Note that sysdig will enable extended /dev/null capture by itself after -detecting that tracers are written there, but that could result in the -truncation of some tracers at the beginning of the capture. -This option allows preventing that. +\f[B]\-\-from\f[R] \f[I]row\f[R] In JSON mode, start output from the +specified row. .PP -\f[B]-v\f[R] \f[I]view_id\f[R], \f[B]--views\f[R]=\f[I]view_id\f[R] -.PD 0 -.P -.PD +\f[B]\-\-to\f[R] \f[I]row\f[R] In JSON mode, stop output at the +specified row. +.PP +\f[B]\-\-sortingcol\f[R] \f[I]col\f[R] In JSON mode, sort output by the +specified column number. +.PP +\f[B]\-X\f[R], \f[B]\-\-print\-hex\-ascii\f[R] When emitting JSON, print +data buffers in both hexadecimal and ASCII form. +.PP +\f[B]\-v\f[R] \f[I]view_id\f[R], \f[B]\-\-view\f[R]=\f[I]view_id\f[R] Run the view with the given ID when csysdig starts. View IDs can be found in the view documentation pages in csysdig. Combine this option with a command line filter for complete output customization. .PP -\f[B]--version\f[R] +\f[B]\-\-version\f[R] .PD 0 .P .PD Print version number. .SS FILTERING -.PP Similarly to what you do with sysdig, you can specify a filter on the command line to restrict the events that csysdig processes. To modify the filter while the program is running, or to add a filter at runtime, click on the filter text in the UI with the mouse. .SS CUSTOMIZING CSYSDIG -.PP csysdig is completely customizable. This means that you can modify any of the csysdig views, and even create your own views. Like sysdig chisels, csysdig views are Lua scripts. -Full information can be found at the following github wiki page: -. +Full information can be found at the following github wiki page: \c +.UR https://github.com/draios/sysdig/wiki/csysdig-View-Format-Reference +.UE \c +\&. .SS FILES -.PP \f[I]/usr/share/sysdig/chisels\f[R] .PD 0 .P @@ -488,10 +442,10 @@ The global views directory. .PD The personal views directory. .SS AUTHOR -.PP Draios Inc. -(dba Sysdig) +(dba Sysdig) \c +.MT info@sysdig.com +.ME \c .SS SEE ALSO -.PP \f[B]sysdig\f[R](8), \f[B]strace\f[R](8), \f[B]tcpdump\f[R](8), \f[B]lsof\f[R](8) diff --git a/userspace/sysdig/man/csysdig.md b/userspace/sysdig/man/csysdig.md index 987b6ed1b8..c444f80dcf 100644 --- a/userspace/sysdig/man/csysdig.md +++ b/userspace/sysdig/man/csysdig.md @@ -156,6 +156,12 @@ MOUSE USAGE COMMAND LINE OPTIONS -------------------- + +**-A**, **--print-ascii** + When emitting JSON, only print the text portion of data buffers and preserve line endings. + +**-B**[_bpf_probe_], **--bpf**[=_bpf_probe_] + Enable live capture using the specified BPF probe instead of the kernel module. If no probe path is provided, csysdig will try to load one automatically. **-d** _period_, **--delay**=_period_ Set the delay between updates, in milliseconds (by default = 2000). This works similarly to the -d option in top. @@ -169,27 +175,36 @@ COMMAND LINE OPTIONS **-h**, **--help** Print this page -**-k**, **--k8s-api** - Enable Kubernetes support by connecting to the API server specified as argument. E.g. "http://admin:password@127.0.0.1:8080". The API server can also be specified via the environment variable SYSDIG_K8S_API. +**--interactive** + Enable interactive JSON mode. csysdig prints `ready` once initialization completes and then accepts UI commands on stdin. -**-K** _btfile | certfile:keyfile[#password][:cacertfile]_, **--k8s-api-cert=**_btfile | certfile:keyfile[#password][:cacertfile]_ - Use the provided files names to authenticate user and (optionally) verify the K8S API server identity. Each entry must specify full (absolute, or relative to the current directory) path to the respective file. Private key password is optional (needed only if key is password protected). CA certificate is optional. For all files, only PEM file format is supported. Specifying CA certificate only is obsoleted - when single entry is provided for this option, it will be interpreted as the name of a file containing bearer token. Note that the format of this command-line option prohibits use of files whose names contain ':' or '#' characters in the file name. Option can also be provided via the environment variable SYSDIG_K8S_API_CERT. +**-j**, **--json** + Emit JSON output instead of the curses interface. **-l**, **--list** List all the fields that can be used in views. + +**--list-views** + List the available csysdig views and exit. + +**--large-environment** + Support environments larger than 4KiB by reading the full environment from `/proc` when needed. **--logfile** _file_ Print program logs into the given file. -**-m** _url[,marathon-url]_, **--mesos-api=**_url[,marathon-url]_ - Enable Mesos support by connecting to the API server specified as argument (e.g. http://admin:password@127.0.0.1:5050). Mesos url is required. Marathon url is optional, defaulting to auto-follow - if Marathon API server is not provided, csysdig will attempt to retrieve (and subsequently follow, if it migrates) the location of Marathon API server from the Mesos master. Note that, with auto-follow, csysdig will likely receive a cluster internal IP address for Marathon API server, so running csysdig with Marathon auto-follow from a node that is not part of Mesos cluster may not work. Additionally, running csysdig with Mesos support on a node that has no containers managed by Mesos is of limited use because, although cluster metadata will be collected, there will be no Mesos/Marathon filtering capability. The API servers can also be specified via the environment variable SYSDIG_MESOS_API. - **-n** _num_, **--numevents**=_num_ Stop capturing after _num_ events **--page-faults** Capture user/kernel major/minor page faults +**--modern-bpf** + Enable live capture using the modern BPF probe instead of the kernel module. + +**--cpus-for-each-buffer** _num_ + Set how many CPUs are assigned to each syscall buffer when using the modern BPF probe. + **-pc**, **-pcontainers**_ Instruct csysdig to use a container-friendly format in its views. This will cause several of the views to contain additional container-related columns. @@ -198,14 +213,26 @@ COMMAND LINE OPTIONS **-r** _readfile_, **--read**=_readfile_ Read the events from _readfile_. + +**--raw** + Print raw output to a regular terminal instead of enabling the curses interface. **-s** _len_, **--snaplen**=_len_ Capture the first _len_ bytes of each I/O buffer. By default, the first 80 bytes are captured. Use this option with caution, it can generate huge trace files. -**-T**, **--force-tracers-capture** - Tell the driver to make sure full buffers are captured from /dev/null, to make sure that tracers are completely captured. Note that sysdig will enable extended /dev/null capture by itself after detecting that tracers are written there, but that could result in the truncation of some tracers at the beginning of the capture. This option allows preventing that. +**--from** _row_ + In JSON mode, start output from the specified row. + +**--to** _row_ + In JSON mode, stop output at the specified row. + +**--sortingcol** _col_ + In JSON mode, sort output by the specified column number. + +**-X**, **--print-hex-ascii** + When emitting JSON, print data buffers in both hexadecimal and ASCII form. -**-v** _view_id_, **--views**=_view_id_ +**-v** _view_id_, **--view**=_view_id_ Run the view with the given ID when csysdig starts. View IDs can be found in the view documentation pages in csysdig. Combine this option with a command line filter for complete output customization. **--version** diff --git a/userspace/sysdig/man/sysdig.8 b/userspace/sysdig/man/sysdig.8 index 829d7b87f3..f549877961 100644 --- a/userspace/sysdig/man/sysdig.8 +++ b/userspace/sysdig/man/sysdig.8 @@ -1,30 +1,12 @@ -.\" Automatically generated by Pandoc 2.18 +.\" Automatically generated by Pandoc 3.5 .\" -.\" Define V font for inline verbatim, using C font in formats -.\" that render this, and otherwise B font. -.ie "\f[CB]x\f[]"x" \{\ -. ftr V B -. ftr VI BI -. ftr VB B -. ftr VBI BI -.\} -.el \{\ -. ftr V CR -. ftr VI CI -. ftr VB CB -. ftr VBI CBI -.\} -.TH "" "" "" "" "" -.hy +.TH "" "" "" "" .SS NAME -.PP -sysdig - the definitive system and process troubleshooting tool +sysdig \- the definitive system and process troubleshooting tool .SS SYNOPSIS -.PP \f[B]sysdig\f[R] [\f[I]option\f[R]]... [\f[I]filter\f[R]] .SS DESCRIPTION -.PP \f[B]Note: if you are interested in an easier to use interface for the sysdig functionality, use the csysdig command line utility.\f[R] .PP @@ -42,7 +24,7 @@ and can be extended through Lua scripts, called chisels. By default, sysdig prints the information for each captured event on a single line, with the following format: .PP -\f[V]*%evt.num %evt.time %evt.cpu %proc.name (%thread.tid) %evt.dir %evt.type %evt.info\f[R] +\f[CR]*%evt.num %evt.time %evt.cpu %proc.name (%thread.tid) %evt.dir %evt.type %evt.info\f[R] .PP where: .IP \[bu] 2 @@ -64,46 +46,46 @@ evt.type is the name of the event, e.g. .IP \[bu] 2 evt.args is the list of event arguments. .PP -The output format can be customized with the -p switch, using any of the -fields listed by \[aq]sysdig -l\[aq]. +The output format can be customized with the \-p switch, using any of +the fields listed by \[aq]sysdig \-l\[aq]. .PP -Using -pc or -pcontainer, the default format will be changed to a -container-friendly one: +Using \-pc or \-pcontainer, the default format will be changed to a +container\-friendly one: .PP -\f[V]*%evt.num %evt.time %evt.cpu %container.name (%container.id) %proc.name (%thread.tid:%thread.vtid) %evt.dir %evt.type %evt.info\f[R] +\f[CR]*%evt.num %evt.time %evt.cpu %container.name (%container.id) %proc.name (%thread.tid:%thread.vtid) %evt.dir %evt.type %evt.info\f[R] .PP \f[B]Trace Files\f[R] .PP -A trace file can be created using the -w switch: +A trace file can be created using the \-w switch: .RS .PP -$ sysdig -w trace.scap +$ sysdig \-w trace.scap .RE .PP -The -s switch can be used to specify how many bytes of each data buffer +The \-s switch can be used to specify how many bytes of each data buffer should be saved to disk. And filters can be used to save only certain events to disk: .RS .PP -$ sysdig -s 2000 -w trace.scap proc.name=cat +$ sysdig \-s 2000 \-w trace.scap proc.name=cat .RE .PP -Trace files can be read this using the -r switch: +Trace files can be read this using the \-r switch: .RS .PP -$ sysdig -r trace.scap +$ sysdig \-r trace.scap .RE .PP \f[B]Filtering\f[R] .PP sysdig filters are specified at the end of the command line. -The simplest filter is a basic field-value check: +The simplest filter is a basic field\-value check: .RS .PP $ sysdig proc.name=cat .RE .PP -The list of available fields can be obtained with \[aq]sysdig -l\[aq]. +The list of available fields can be obtained with \[aq]sysdig \-l\[aq]. Filter expressions can use one of these comparison operators: \f[I]=\f[R], \f[I]!=\f[R], \f[I]<\f[R], \f[I]<=\f[R], \f[I]>\f[R], \f[I]>=\f[R], \f[I]contains\f[R], \f[I]icontains\f[R], \f[I]in\f[R] and @@ -130,71 +112,71 @@ stream to perform useful actions. To get the list of available chisels, type .RS .PP -$ sysdig -cl +$ sysdig \-cl .RE .PP To get details about a specific chisel, type .RS .PP -$ sysdig -i spy_ip +$ sysdig \-i spy_ip .RE .PP -To run one of the chisels, you use the -c flag, e.g. +To run one of the chisels, you use the \-c flag, e.g. .RS .PP -$ sysdig -c topfiles_bytes +$ sysdig \-c topfiles_bytes .RE .PP If a chisel needs arguments, you specify them after the chisel name: .RS .PP -$ sysdig -c spy_ip 192.168.1.157 +$ sysdig \-c spy_ip 192.168.1.157 .RE .PP If a chisel has more than one argument, specify them after the chisel name, enclosed in quotes: .RS .PP -$ sysdig -c chisel_name \[dq]arg1 arg2 arg3\[dq] +$ sysdig \-c chisel_name \[dq]arg1 arg2 arg3\[dq] .RE .PP Chisels can be combined with filters: .RS .PP -$ sysdig -c topfiles_bytes \[dq]not fd.name contains /dev\[dq] +$ sysdig \-c topfiles_bytes \[dq]not fd.name contains /dev\[dq] .RE .SS OPTIONS +\f[B]\-A\f[R], \f[B]\-\-print\-ascii\f[R] Only print the text portion of +data buffers, and echo end\-of\-lines. +This is useful to only display human\-readable data. .PP -\f[B]-A\f[R], \f[B]--print-ascii\f[R] Only print the text portion of -data buffers, and echo end-of-lines. -This is useful to only display human-readable data. -.PP -\f[B]-b\f[R], \f[B]--print-base64\f[R] Print data buffers in base64. +\f[B]\-b\f[R], \f[B]\-\-print\-base64\f[R] Print data buffers in base64. This is useful for encoding binary data that needs to be used over media designed to handle textual data (i.e., terminal or json). .PP -\f[B]-c\f[R] \f[I]chiselname\f[R] \f[I]chiselargs\f[R], -\f[B]--chisel\f[R]=\f[I]chiselname\f[R] \f[I]chiselargs\f[R] run the +\f[B]\-c\f[R] \f[I]chiselname\f[R] \f[I]chiselargs\f[R], +\f[B]\-\-chisel\f[R]=\f[I]chiselname\f[R] \f[I]chiselargs\f[R] run the specified chisel. If the chisel require arguments, they must be specified in the command line after the name. .PP -\f[B]-C\f[R] \f[I]filesize\f[R] Break a capture into separate files, and -limit the size of each file based on the specified number of megabytes. +\f[B]\-C\f[R] \f[I]filesize\f[R] Break a capture into separate files, +and limit the size of each file based on the specified number of +megabytes. The units of \f[I]filesize\f[R] are millions of bytes (10\[ha]6, not 2\[ha]20). -Use in conjunction with \f[B]-W\f[R] to enable automatic file rotation. +Use in conjunction with \f[B]\-W\f[R] to enable automatic file rotation. Otherwise, new files will continue to be created until the capture is manually stopped. .PP -Files will have the name specified by \f[B]-w\f[R] with a counter added +Files will have the name specified by \f[B]\-w\f[R] with a counter added starting at 0. .PP -\f[B]-cl\f[R], \f[B]--list-chisels\f[R] lists the available chisels. +\f[B]\-cl\f[R], \f[B]\-\-list\-chisels\f[R] lists the available chisels. Sysdig looks for chisels in the following directories: ./chisels, \[ti]/.chisels and /usr/share/sysdig/chisels. .PP -\f[B]-d\f[R], \f[B]--displayflt\f[R] Make the given filter a display +\f[B]\-d\f[R], \f[B]\-\-displayflt\f[R] Make the given filter a display one. Setting this option causes the events to be filtered after being parsed by the state system. @@ -202,29 +184,29 @@ Events are normally filtered before being analyzed, which is more efficient, but can cause state (e.g. FD names) to be lost. .PP -\f[B]-D\f[R], \f[B]--debug\f[R] Capture events about sysdig itself, +\f[B]\-D\f[R], \f[B]\-\-debug\f[R] Capture events about sysdig itself, display internal events in addition to system events, and print additional logging on standard error. .PP -\f[B]-E\f[R], \f[B]--exclude-users\f[R] Don\[aq]t create the user/group -tables by querying the OS when sysdig starts. +\f[B]\-E\f[R], \f[B]\-\-exclude\-users\f[R] Don\[aq]t create the +user/group tables by querying the OS when sysdig starts. This also means that no user or group info will be written to the -tracefile by the \f[B]-w\f[R] flag. +tracefile by the \f[B]\-w\f[R] flag. The user/group tables are necessary to use filter fields like user.name or group.name. However, creating them can increase sysdig\[aq]s startup time. Moreover, they contain information that could be privacy sensitive. .PP -\f[B]-e\f[R] \f[I]numevents\f[R] Break a capture into separate files, +\f[B]\-e\f[R] \f[I]numevents\f[R] Break a capture into separate files, and limit the size of each file based on the specified number of events. -Use in conjunction with \f[B]-W\f[R] to enable automatic file rotation. +Use in conjunction with \f[B]\-W\f[R] to enable automatic file rotation. Otherwise, new files will continue to be created until the capture is manually stopped. .PP -Files will have the name specified by \f[B]-w\f[R] with a counter added +Files will have the name specified by \f[B]\-w\f[R] with a counter added starting at 0. .PP -\f[B]-F\f[R], \f[B]--fatfile\f[R] Enable fatfile mode. +\f[B]\-F\f[R], \f[B]\-\-fatfile\f[R] Enable fatfile mode. When writing in fatfile mode, the output file will contain events that will be invisible when reading the file, but that are necessary to fully reconstruct the state. @@ -238,168 +220,161 @@ With fatfile mode, those events are still saved to file, but Be aware that using this flag might generate substantially bigger traces files. .PP -\f[B]--filter-proclist\f[R] apply the filter to the process table. +\f[B]\-\-filter\-proclist\f[R] apply the filter to the process table. A full dump of /proc is typically included in any trace file to make sure all the state required to decode events is in the file. This could cause the file to contain unwanted or sensitive information. Using this flag causes the command line filter to be applied to the /proc dump as well. .PP -\f[B]-G\f[R] \f[I]numseconds\f[R] Break a capture into separate files, +\f[B]\-G\f[R] \f[I]numseconds\f[R] Break a capture into separate files, and limit the size of each file based on the specified number of seconds. -Use in conjunction with \f[B]-W\f[R] to enable automatic file rotation. +Use in conjunction with \f[B]\-W\f[R] to enable automatic file rotation. Otherwise, new files will continue to be created until the capture is manually stopped. .PP -Files will have the name specified by \f[B]-w\f[R] which should include +Files will have the name specified by \f[B]\-w\f[R] which should include a time format as defined by strftime(3). If no time format is specified, a counter will be used. .PP -\f[B]-h\f[R], \f[B]--help\f[R] Print this page +\f[B]\-h\f[R], \f[B]\-\-help\f[R] Print this page .PP -\f[B]-H\f[R] \f[I]pluginname\f[R][:\f[I]initconfig\f[R]], -\f[B]--plugin\f[R] \f[I]pluginname\f[R][:\f[I]initconfig\f[R]] Registers -a plugin, using the passed init config if present. +\f[B]\-H\f[R] \f[I]pluginname\f[R][:\f[I]initconfig\f[R]], +\f[B]\-\-plugin\f[R] \f[I]pluginname\f[R][:\f[I]initconfig\f[R]] +Registers a plugin, using the passed init config if present. A path can also be used as pluginname. The format of initconf is controlled by the plugin, refer to each plugin\[aq]s documentation to learn about it. .PP -\f[B]-I\f[R] \f[I]pluginname\f[R][:\f[I]openparams\f[R]], -\f[B]--input\f[R] \f[I]pluginname\f[R][:\f[I]openparams\f[R]] Capture +\f[B]\-I\f[R] \f[I]pluginname\f[R][:\f[I]openparams\f[R]], +\f[B]\-\-input\f[R] \f[I]pluginname\f[R][:\f[I]openparams\f[R]] Capture events using the plugin with name pluginname, passing to the plugin the openparams string as parameters. The format of inputargs is controller by the plugin, refer to each plugin\[aq]s documentation to learn about it. The event sources available for capture vary depending on which plugins have been installed. -You can list the plugins that have been loaded by using the -Il flag. +You can list the plugins that have been loaded by using +\f[CR]\-I l\f[R]. .PP -\f[B]-Il\f[R], \f[B]--list-inputs\f[R] List the loaded plugins. +\f[B]\-I l\f[R] List the loaded plugins. Sysdig looks for plugins in the following directories: ./plugins, \[ti]/.plugins, /usr/share/sysdig/plugins. .PP -\f[B]--plugin-config-file\f[R] Load the plugin configuration from a -Falco-compatible yaml config file. -Mixing this option with \[aq]-H\[aq] or \[aq]-I\[aq] is unsupported. -See the plugin section in for -additional informations. -.PP -\f[B]-i \f[BI]chiselname\f[B]\f[R], \f[B]--chisel-info=\f[R]_chiselname_ -Get a longer description and the arguments associated with a chisel -found in the -cl option list. -.PP -\f[B]-j\f[R], \f[B]--json\f[R] Emit output as json, data buffer encoding -will depend from the print format selected. -.PP -\f[B]-k\f[R], \f[B]--k8s-api\f[R] Enable Kubernetes support by -connecting to the API server specified as argument. -E.g. -\[dq]\[dq]. -The API server can also be specified via the environment variable -SYSDIG_K8S_API. -.PP -\f[B]-K\f[R] \f[I]btfile | -certfile:keyfile[#password][:cacertfile]\f[R], -\f[B]--k8s-api-cert=\f[R]_btfile | -certfile:keyfile[#password][:cacertfile]_ Use the provided files names -to authenticate user and (optionally) verify the K8S API server -identity. -Each entry must specify full (absolute, or relative to the current -directory) path to the respective file. -Private key password is optional (needed only if key is password -protected). -CA certificate is optional. -For all files, only PEM file format is supported. -Specifying CA certificate only is obsoleted - when single entry is -provided for this option, it will be interpreted as the name of a file -containing bearer token. -Note that the format of this command-line option prohibits use of files -whose names contain \[aq]:\[aq] or \[aq]#\[aq] characters in the file -name. -Option can also be provided via the environment variable -SYSDIG_K8S_API_CERT. -.PP -\f[B]-L\f[R], \f[B]--list-events\f[R] List the events that the engine -supports -.PP -\f[B]-l\f[R], \f[B]--list\f[R] List the fields that can be used for +\f[B]\-\-plugin\-config\-file\f[R] Load the plugin configuration from a +Falco\-compatible yaml config file. +Mixing this option with \[aq]\-H\[aq] or \[aq]\-I\[aq] is unsupported. +See the plugin section in \c +.UR https://falco.org/docs/configuration/ +.UE \c +\ for additional informations. +.PP +\f[B]\-i \f[BI]chiselname\f[B]\f[R], +\f[B]\-\-chisel\-info=\f[R]_chiselname_ Get a longer description and the +arguments associated with a chisel found in the \-cl option list. +.PP +\f[B]\-j\f[R], \f[B]\-\-json\f[R] Emit output as json, data buffer +encoding will depend from the print format selected. +.PP +\f[B]\-L\f[R], \f[B]\-\-list\-events\f[R] List the events that the +engine supports +.PP +\f[B]\-l\f[R], \f[B]\-\-list\f[R] List the fields that can be used for filtering and output formatting. -Use -lv to get additional information for each field. -.PP -\f[B]--list-markdown\f[R] Like -l, but produces markdown output -.PP -\f[B]-m\f[R] \f[I]url[,marathon-url]\f[R], -\f[B]--mesos-api=\f[R]_url[,marathon-url]_ Enable Mesos support by -connecting to the API server specified as argument (e.g. -). -Mesos url is required. -Marathon url is optional, defaulting to auto-follow - if Marathon API -server is not provided, sysdig will attempt to retrieve (and -subsequently follow, if it migrates) the location of Marathon API server -from the Mesos master. -Note that, with auto-follow, sysdig will likely receive a cluster -internal IP address for Marathon API server, so running sysdig with -Marathon auto-follow from a node that is not part of Mesos cluster may -not work. -Additionally, running sysdig with Mesos support on a node that has no -containers managed by Mesos is of limited use because, although cluster -metadata will be collected, there will be no Mesos/Marathon filtering -capability. -The API servers can also be specified via the environment variable -SYSDIG_MESOS_API. -.PP -\f[B]-M\f[R] \f[I]num_seconds\f[R] Stop collecting after reaching -.PP -\f[B]-n\f[R] \f[I]num\f[R], \f[B]--numevents\f[R]=\f[I]num\f[R] +.PP +\f[B]\-\-list\-markdown\f[R] Like \-l, but produces markdown output +.PP +\f[B]\-\-libs\-version\f[R] Print the falcosecurity/libs version. +.PP +\f[B]\-\-log\-level\f[R]=\f[I]trace|debug|info|notice|warning|error|critical|fatal\f[R] +Select the minimum log level. +Useful together with \f[B]\-\-debug\f[R]. +.PP +\f[B]\-\-color\f[R]=\f[I]true|false|force\f[R] Control colorized output. +\f[CR]true\f[R] enables color when stdout is a terminal, +\f[CR]false\f[R] disables it, and \f[CR]force\f[R] always enables it. +.PP +\f[B]\-\-filter\-proclist\f[R] Apply the command\-line filter to the +\f[CR]/proc\f[R] dump included in trace files. +.PP +\f[B]\-\-plugin\-info\f[R] \f[I]pluginname\f[R] Print detailed +information for a single plugin and exit. +.PP +\f[B]\-\-plugin\-config\-file\f[R] \f[I]file\f[R] Load plugin +configuration from a Falco\-compatible YAML configuration file. +.PP +\f[B]\-g\f[R] \f[I]config\f[R], +\f[B]\-\-gvisor\-config\f[R]=\f[I]config\f[R] Parse events from gVisor +using the provided configuration file. +.PP +\f[B]\-\-gvisor\-root\f[R] \f[I]path\f[R] Set the gVisor root directory +used to resolve container state. +.PP +\f[B]\-\-gvisor\-generate\-config\f[R][=\f[I]socket\f[R]] Generate a +gVisor configuration file and print it to standard output. +.PP +\f[B]\-M\f[R] \f[I]num_seconds\f[R] Stop collecting after reaching +.PP +\f[B]\-n\f[R] \f[I]num\f[R], \f[B]\-\-numevents\f[R]=\f[I]num\f[R] .PD 0 .P .PD Stop capturing after \f[I]num\f[R] events .PP -\f[B]--page-faults\f[R] Capture user/kernel major/minor page faults +\f[B]\-\-page\-faults\f[R] Capture user/kernel major/minor page faults +.PP +\f[B]\-\-large\-environment\f[R] Support environments larger than 4KiB +by reading the full environment from \f[CR]/proc\f[R] when needed. +.PP +\f[B]\-\-modern\-bpf\f[R] Enable live capture using the modern BPF probe +instead of the kernel module. +.PP +\f[B]\-\-cpus\-for\-each\-buffer\f[R] \f[I]num\f[R] Set how many CPUs +are assigned to each syscall buffer when using the modern BPF probe. .PP -\f[B]-P\f[R], \f[B]--progress\f[R] +\f[B]\-P\f[R], \f[B]\-\-progress\f[R] .PD 0 .P .PD Print progress on stderr while processing trace files. .PP -\f[B]-p\f[R] \f[I]outputformat\f[R], -\f[B]--print\f[R]=\f[I]outputformat\f[R] +\f[B]\-p\f[R] \f[I]outputformat\f[R], +\f[B]\-\-print\f[R]=\f[I]outputformat\f[R] .PD 0 .P .PD Specify the format to be used when printing the events. -With -pc or -pcontainer will use a container-friendly format. -With -pk or -pkubernetes will use a kubernetes-friendly format. -With -pm or -pmesos will use a mesos-friendly format. -Specifying \f[B]-pp\f[R] on the command line will cause sysdig to print +With \-pc or \-pcontainer will use a container\-friendly format. +With \-pk or \-pkubernetes will use a kubernetes\-friendly format. +With \-pm or \-pmesos will use a mesos\-friendly format. +Specifying \f[B]\-pp\f[R] on the command line will cause sysdig to print the default command line format and exit. .PP -\f[B]-q\f[R], \f[B]--quiet\f[R] +\f[B]\-q\f[R], \f[B]\-\-quiet\f[R] .PD 0 .P .PD Don\[aq]t print events on the screen. Useful when dumping to disk. .PP -\f[B]-r\f[R] \f[I]readfile\f[R], \f[B]--read\f[R]=\f[I]readfile\f[R] +\f[B]\-r\f[R] \f[I]readfile\f[R], \f[B]\-\-read\f[R]=\f[I]readfile\f[R] .PD 0 .P .PD Read the events from \f[I]readfile\f[R]. .PP -\f[B]-R\f[R], \f[B]--resolve-ports\f[R] Resolve port numbers to names. +\f[B]\-R\f[R], \f[B]\-\-resolve\-ports\f[R] Resolve port numbers to +names. .PP -\f[B]-S\f[R], \f[B]--summary\f[R] +\f[B]\-S\f[R], \f[B]\-\-summary\f[R] .PD 0 .P .PD print the event summary (i.e. the list of the top events) when the capture ends. .PP -\f[B]-s\f[R] \f[I]len\f[R], \f[B]--snaplen\f[R]=\f[I]len\f[R] +\f[B]\-s\f[R] \f[I]len\f[R], \f[B]\-\-snaplen\f[R]=\f[I]len\f[R] .PD 0 .P .PD @@ -407,28 +382,18 @@ Capture the first \f[I]len\f[R] bytes of each I/O buffer. By default, the first 80 bytes are captured. Use this option with caution, it can generate huge trace files. .PP -\f[B]-t\f[R] \f[I]timetype\f[R], \f[B]--timetype\f[R]=\f[I]timetype\f[R] +\f[B]\-t\f[R] \f[I]timetype\f[R], +\f[B]\-\-timetype\f[R]=\f[I]timetype\f[R] .PD 0 .P .PD Change the way event time is displayed. -Accepted values are \f[B]h\f[R] for human-readable string, \f[B]a\f[R] +Accepted values are \f[B]h\f[R] for human\-readable string, \f[B]a\f[R] for absolute timestamp from epoch, \f[B]r\f[R] for relative time from the first displayed event, \f[B]d\f[R] for delta between event enter and exit, and \f[B]D\f[R] for delta from the previous event. .PP -\f[B]-T\f[R], \f[B]--force-tracers-capture\f[R] -.PD 0 -.P -.PD -Tell the driver to make sure full buffers are captured from /dev/null, -to make sure that tracers are completely captured. -Note that sysdig will enable extended /dev/null capture by itself after -detecting that tracers are written there, but that could result in the -truncation of some tracers at the beginning of the capture. -This option allows preventing that. -.PP -\f[B]--unbuffered\f[R] +\f[B]\-\-unbuffered\f[R] .PD 0 .P .PD @@ -437,7 +402,7 @@ This causes every single line emitted by sysdig to be flushed, which generates higher CPU usage but is useful when piping sysdig\[aq]s output into another process or into a script. .PP -\f[B]-v\f[R], \f[B]--verbose\f[R] +\f[B]\-v\f[R], \f[B]\-\-verbose\f[R] .PD 0 .P .PD @@ -445,51 +410,51 @@ Verbose output. This flag will cause the full content of text and binary buffers to be printed on screen, instead of being truncated to 40 characters. Note that data buffers length is still limited by the snaplen (refer to -the -s flag documentation) -v will also make sysdig print some summary +the \-s flag documentation) \-v will also make sysdig print some summary information at the end of the capture. .PP -\f[B]--version\f[R] +\f[B]\-\-version\f[R] .PD 0 .P .PD Print version number. .PP -\f[B]-w\f[R] \f[I]writefile\f[R], \f[B]--write\f[R]=\f[I]writefile\f[R] +\f[B]\-w\f[R] \f[I]writefile\f[R], +\f[B]\-\-write\f[R]=\f[I]writefile\f[R] .PD 0 .P .PD Write the captured events to \f[I]writefile\f[R]. .PP -\f[B]-W\f[R] \f[I]num\f[R] +\f[B]\-W\f[R] \f[I]num\f[R] .PD 0 .P .PD Turn on file rotation for continuous capture, and limit the number of files created to the specified number. Once the cap is reached, older files will be overwritten (ring buffer). -Use in conjunction with the \f[B]-C\f[R] / \f[B]-G\f[R] / \f[B]-e\f[R] -options to limit the size of each file based on number of megabytes, -seconds, and/or events (respectively). +Use in conjunction with the \f[B]\-C\f[R] / \f[B]\-G\f[R] / +\f[B]\-e\f[R] options to limit the size of each file based on number of +megabytes, seconds, and/or events (respectively). .PP -\f[B]-x\f[R], \f[B]--print-hex\f[R] +\f[B]\-x\f[R], \f[B]\-\-print\-hex\f[R] .PD 0 .P .PD Print data buffers in hex. .PP -\f[B]-X\f[R], \f[B]--print-hex-ascii\f[R] +\f[B]\-X\f[R], \f[B]\-\-print\-hex\-ascii\f[R] .PD 0 .P .PD Print data buffers in hex and ASCII. .PP -\f[B]-z\f[R], \f[B]--compress\f[R] +\f[B]\-z\f[R], \f[B]\-\-compress\f[R] .PD 0 .P .PD -Used with \f[B]-w\f[R], enables compression for tracefiles. +Used with \f[B]\-w\f[R], enables compression for tracefiles. .SS EXAMPLES -.PP Capture all the events from the live system and print them to screen .RS .PP @@ -499,26 +464,26 @@ $ sysdig Capture all the events from the live system and save them to disk .RS .PP -$ sysdig -w dumpfile.scap +$ sysdig \-w dumpfile.scap .RE .PP Capture all the events in the latest 24 hours and save them to disk organized in files containing 1 hour of system activity each .RS .PP -$ sysdig -G 3600 -W 24 -w dumpfile.scap +$ sysdig \-G 3600 \-W 24 \-w dumpfile.scap .RE .PP Read events from a file and print them to screen .RS .PP -$ sysdig -r dumpfile.scap +$ sysdig \-r dumpfile.scap .RE .PP Prepare a sanitized version of a system capture .RS .PP -$ sysdig -r dumpfile.scap \[aq]not evt.buffer contains foo\[aq] -w +$ sysdig \-r dumpfile.scap \[aq]not evt.buffer contains foo\[aq] \-w cleandump.scap .RE .PP @@ -531,22 +496,21 @@ $ sysdig proc.name=cat and evt.type=open Print the name of the files opened by cat .RS .PP -$ sysdig -p\[dq]%evt.arg.name\[dq] proc.name=cat and evt.type=open +$ sysdig \-p\[dq]%evt.arg.name\[dq] proc.name=cat and evt.type=open .RE .PP List the available chisels .RS .PP -$ sysdig -cl +$ sysdig \-cl .RE .PP Use the spy_ip chisel to look at the data exchanged with 192.168.1.157: .RS .PP -$ sysdig -c spy_ip 192.168.1.157 +$ sysdig \-c spy_ip 192.168.1.157 .RE .SS FILES -.PP \f[I]/usr/share/sysdig/chisels\f[R] .PD 0 .P @@ -565,10 +529,10 @@ mode. While it is possible to use sysdig with LuaJIT in Lua 5.2 mode or regular Lua, some chisels may not work as expected. .SS AUTHOR -.PP Draios Inc. -aka sysdig +aka sysdig \c +.MT info@sysdigcloud.com +.ME \c .SS SEE ALSO -.PP \f[B]csysdig\f[R](8), \f[B]strace\f[R](8), \f[B]tcpdump\f[R](8), \f[B]lsof\f[R](8) diff --git a/userspace/sysdig/man/sysdig.md b/userspace/sysdig/man/sysdig.md index b86b4af2c0..675683710b 100644 --- a/userspace/sysdig/man/sysdig.md +++ b/userspace/sysdig/man/sysdig.md @@ -139,9 +139,9 @@ OPTIONS Registers a plugin, using the passed init config if present. A path can also be used as pluginname. The format of initconf is controlled by the plugin, refer to each plugin's documentation to learn about it. **-I** _pluginname_[:_openparams_], **--input** _pluginname_[:_openparams_] - Capture events using the plugin with name pluginname, passing to the plugin the openparams string as parameters. The format of inputargs is controller by the plugin, refer to each plugin's documentation to learn about it. The event sources available for capture vary depending on which plugins have been installed. You can list the plugins that have been loaded by using the -Il flag. + Capture events using the plugin with name pluginname, passing to the plugin the openparams string as parameters. The format of inputargs is controller by the plugin, refer to each plugin's documentation to learn about it. The event sources available for capture vary depending on which plugins have been installed. You can list the plugins that have been loaded by using `-I l`. -**-Il**, **--list-inputs** +**-I l** List the loaded plugins. Sysdig looks for plugins in the following directories: ./plugins, ~/.plugins, /usr/share/sysdig/plugins. **--plugin-config-file** @@ -153,23 +153,41 @@ OPTIONS **-j**, **--json** Emit output as json, data buffer encoding will depend from the print format selected. -**-k**, **--k8s-api** - Enable Kubernetes support by connecting to the API server specified as argument. E.g. "http://admin:password@127.0.0.1:8080". The API server can also be specified via the environment variable SYSDIG_K8S_API. - -**-K** _btfile | certfile:keyfile[#password][:cacertfile]_, **--k8s-api-cert=**_btfile | certfile:keyfile[#password][:cacertfile]_ - Use the provided files names to authenticate user and (optionally) verify the K8S API server identity. Each entry must specify full (absolute, or relative to the current directory) path to the respective file. Private key password is optional (needed only if key is password protected). CA certificate is optional. For all files, only PEM file format is supported. Specifying CA certificate only is obsoleted - when single entry is provided for this option, it will be interpreted as the name of a file containing bearer token. Note that the format of this command-line option prohibits use of files whose names contain ':' or '#' characters in the file name. Option can also be provided via the environment variable SYSDIG_K8S_API_CERT. - **-L**, **--list-events** List the events that the engine supports **-l**, **--list** - List the fields that can be used for filtering and output formatting. Use -lv to get additional information for each field. + List the fields that can be used for filtering and output formatting. **--list-markdown** Like -l, but produces markdown output -**-m** _url[,marathon-url]_, **--mesos-api=**_url[,marathon-url]_ - Enable Mesos support by connecting to the API server specified as argument (e.g. http://admin:password@127.0.0.1:5050). Mesos url is required. Marathon url is optional, defaulting to auto-follow - if Marathon API server is not provided, sysdig will attempt to retrieve (and subsequently follow, if it migrates) the location of Marathon API server from the Mesos master. Note that, with auto-follow, sysdig will likely receive a cluster internal IP address for Marathon API server, so running sysdig with Marathon auto-follow from a node that is not part of Mesos cluster may not work. Additionally, running sysdig with Mesos support on a node that has no containers managed by Mesos is of limited use because, although cluster metadata will be collected, there will be no Mesos/Marathon filtering capability. The API servers can also be specified via the environment variable SYSDIG_MESOS_API. +**--libs-version** + Print the falcosecurity/libs version. + +**--log-level**=_trace|debug|info|notice|warning|error|critical|fatal_ + Select the minimum log level. Useful together with **--debug**. + +**--color**=_true|false|force_ + Control colorized output. `true` enables color when stdout is a terminal, `false` disables it, and `force` always enables it. + +**--filter-proclist** + Apply the command-line filter to the `/proc` dump included in trace files. + +**--plugin-info** _pluginname_ + Print detailed information for a single plugin and exit. + +**--plugin-config-file** _file_ + Load plugin configuration from a Falco-compatible YAML configuration file. + +**-g** _config_, **--gvisor-config**=_config_ + Parse events from gVisor using the provided configuration file. + +**--gvisor-root** _path_ + Set the gVisor root directory used to resolve container state. + +**--gvisor-generate-config**[=_socket_] + Generate a gVisor configuration file and print it to standard output. **-M** _num_seconds_ Stop collecting after reaching @@ -180,6 +198,15 @@ OPTIONS **--page-faults** Capture user/kernel major/minor page faults +**--large-environment** + Support environments larger than 4KiB by reading the full environment from `/proc` when needed. + +**--modern-bpf** + Enable live capture using the modern BPF probe instead of the kernel module. + +**--cpus-for-each-buffer** _num_ + Set how many CPUs are assigned to each syscall buffer when using the modern BPF probe. + **-P**, **--progress** Print progress on stderr while processing trace files. @@ -204,9 +231,6 @@ OPTIONS **-t** _timetype_, **--timetype**=_timetype_ Change the way event time is displayed. Accepted values are **h** for human-readable string, **a** for absolute timestamp from epoch, **r** for relative time from the first displayed event, **d** for delta between event enter and exit, and **D** for delta from the previous event. -**-T**, **--force-tracers-capture** - Tell the driver to make sure full buffers are captured from /dev/null, to make sure that tracers are completely captured. Note that sysdig will enable extended /dev/null capture by itself after detecting that tracers are written there, but that could result in the truncation of some tracers at the beginning of the capture. This option allows preventing that. - **--unbuffered** Turn off output buffering. This causes every single line emitted by sysdig to be flushed, which generates higher CPU usage but is useful when piping sysdig's output into another process or into a script. diff --git a/userspace/sysdig/sysdig.cpp b/userspace/sysdig/sysdig.cpp index f02c5c6780..db79c38172 100644 --- a/userspace/sysdig/sysdig.cpp +++ b/userspace/sysdig/sysdig.cpp @@ -28,6 +28,7 @@ limitations under the License. #include #include #include +#include #include #include @@ -55,12 +56,12 @@ limitations under the License. #include "utils/supported_events.h" #include "utils/supported_fields.h" +#include + #ifdef _WIN32 -#include "win32/getopt.h" #include #else #include -#include #include #endif @@ -81,6 +82,95 @@ enum color_term_out { static void usage(); +// +// Command-line options structure (for CLI11 refactoring) +// +struct sysdig_options { + // Common options + bool help = false; + bool version = false; + bool libs_version = false; + bool quiet = false; + bool verbose = false; + bool debug = false; + bool json = false; + bool unbuffered = false; + bool compress = false; + bool print_progress = false; + bool exclude_users = false; + bool summary = false; + bool resolve_ports = false; + bool fatfile = false; + + // Display format options + bool print_ascii = false; + bool print_base64 = false; + bool print_hex = false; + bool print_hex_ascii = false; + std::string print_format; + + // Capture options + std::string bpf_probe; + bool modern_bpf = false; + int cpus_for_each_buffer = 0; + bool page_faults = false; + bool large_environment = false; + + // I/O options + std::vector read_files; + std::string write_file; + int snaplen = 0; + uint64_t num_events = std::numeric_limits::max(); + int max_seconds = 0; + + // File rotation options + int file_size_mb = 0; + int duration_seconds = 0; + int file_limit = 0; + unsigned long event_limit = 0; + + // Filter options + bool display_filter = false; + bool filter_proclist = false; + std::vector suppress_comms; + + // Time format + std::string time_format; + + // Color output + std::string color_mode; + + // Log level + std::string log_level; + + // Plugin options + std::vector plugins; + std::string input_plugin; + std::string plugin_config_file; + std::string plugin_info; + + // gVisor options + std::string gvisor_config; + std::string gvisor_root; + std::string gvisor_generate_config; + + // List options + bool list_fields = false; + bool list_fields_markdown = false; + std::string list_fields_source; + bool list_events = false; + +#ifdef HAS_CHISELS + // Chisel options + std::vector chisels; + bool list_chisels = false; + std::string chisel_info; +#endif + + // Remaining positional args (filter) + std::vector filter_args; +}; + // // Helper functions // @@ -228,7 +318,7 @@ static void usage() " and https://falco.org/docs/plugins/plugin-api-reference/#ss-instance-t-plugin-open-ss-plugin-t-s-const-char-params-int32-t-rc-required-yes for more infos.\n" " The event sources available for capture vary depending on which \n" " plugins have been installed.\n" -" -Il Lists the loaded plugins. If no plugin has been registered through '-H',\n" +" -I l Lists the loaded plugins. If no plugin has been registered through '-H',\n" " Sysdig looks for plugins in the directories \n" " specified by ;-separated environment variable SYSDIG_PLUGIN_DIR and\n" " in " SYSDIG_PLUGINS_DIR ".\n" @@ -241,8 +331,7 @@ static void usage() " print format selected.\n" " -L, --list-events List the events that the engine supports\n" " -l, --list List the fields that can be used for filtering and output\n" -" formatting. Use -lv to get additional information for each\n" -" field.\n" +" formatting.\n" " --libs-version Print the falcosecurity/libs version\n" " --large-environment\n" " Support environments larger than 4KiB\n" @@ -514,6 +603,7 @@ static void initialize_chisels() static void parse_chisel_args( sinsp_chisel* ch, std::shared_ptr filter_factory, + const std::string& chisel_name, int optind, int argc, char **argv, int32_t* n_filterargs) { uint32_t nargs = ch->get_n_args(); @@ -524,7 +614,7 @@ static void parse_chisel_args( { if(optind > (int32_t)argc) { - throw sinsp_exception("invalid number of arguments for chisel " + std::string(optarg) + ", " + std::to_string((long long int)nargs) + " expected."); + throw sinsp_exception("invalid number of arguments for chisel " + chisel_name + ", " + std::to_string((long long int)nargs) + " expected."); } else if(optind < (int32_t)argc) { @@ -575,12 +665,67 @@ static void parse_chisel_args( { if(nreqargs != 0) { - throw sinsp_exception("missing arguments for chisel " + std::string(optarg)); + throw sinsp_exception("missing arguments for chisel " + chisel_name); } } } } +static bool is_short_option_with_value(const std::string& arg, const std::string& opts) +{ + return arg.size() > 2 && arg[0] == '-' && arg[1] != '-' && opts.find(arg[1]) != std::string::npos; +} + +static std::vector normalize_sysdig_argv(int argc, char** argv) +{ + std::vector normalized; + normalized.reserve(argc); + if(argc > 0) + { + normalized.emplace_back(argv[0]); + } + + for(int i = 1; i < argc; ++i) + { + std::string arg = argv[i]; + if(arg == "-cl") + { + normalized.emplace_back("--list-chisels"); + continue; + } + + if(is_short_option_with_value(arg, "BCcegGHIilMnprstUwW")) + { + normalized.emplace_back(arg.substr(0, 2)); + normalized.emplace_back(arg.substr(2)); + continue; + } + + normalized.emplace_back(std::move(arg)); + } + + return normalized; +} + +static std::vector argv_ptrs(std::vector& args) +{ + std::vector res; + res.reserve(args.size()); + for(auto& arg : args) + { + res.push_back(arg.data()); + } + return res; +} + +static int count_enabled_formats(const sysdig_options& opts) +{ + return (opts.print_ascii ? 1 : 0) + + (opts.print_base64 ? 1 : 0) + + (opts.print_hex ? 1 : 0) + + (opts.print_hex_ascii ? 1 : 0); +} + static void free_chisels() { #ifdef HAS_CHISELS @@ -975,6 +1120,205 @@ std::string escape_output_format(const std::string& s) return ss.str(); } +// +// CLI11-based argument parser +// +sysdig_options parse_args_cli11(int argc, char **argv) +{ + sysdig_options opts; + + CLI::App app{"sysdig - the universal system visibility tool with native support for containers\n" + "sysdig version " SYSDIG_VERSION}; + + // Disable help flag so we can handle it ourselves for backwards compatibility + app.set_help_flag(""); + app.allow_extras(); // Allow extra arguments for filter + + // Common options + app.add_flag("-h,--help", opts.help, "Print this help message"); + app.add_flag("--version", opts.version, "Print version number"); + app.add_flag("--libs-version", opts.libs_version, "Print the falcosecurity/libs version"); + app.add_flag("-q,--quiet", opts.quiet, "Don't print events on the screen (useful when dumping to disk)"); + app.add_flag("-v,--verbose", opts.verbose, "Verbose output"); + app.add_flag("-D,--debug", opts.debug, "Capture events about sysdig itself and display internal events"); + app.add_flag("-j,--json", opts.json, "Emit output as json"); + app.add_flag("--unbuffered", opts.unbuffered, "Turn off output buffering"); + app.add_flag("-z,--compress", opts.compress, "Used with -w, enables compression for trace files"); + app.add_flag("-P,--progress", opts.print_progress, "Print progress on stderr while processing trace files"); + app.add_flag("-E,--exclude-users", opts.exclude_users, "Don't create user/group tables"); + app.add_flag("-S,--summary", opts.summary, "Print event summary when capture ends"); + app.add_flag("-R,--resolve-ports", opts.resolve_ports, "Resolve port numbers to names"); + + // Display format options + app.add_flag("-A,--print-ascii", opts.print_ascii, + "Print only text portion of data buffers"); + app.add_flag("-b,--print-base64", opts.print_base64, + "Print data buffers in base64"); + app.add_flag("-x,--print-hex", opts.print_hex, + "Print data buffers in hex"); + app.add_flag("-X,--print-hex-ascii", opts.print_hex_ascii, + "Print data buffers in hex and ASCII"); + + app.add_option("-p,--print", opts.print_format, "Specify the format for printing events") + ->type_name("FORMAT"); + + // Capture options + app.add_option("-B,--bpf", opts.bpf_probe, + "Enable live capture using BPF probe") + ->expected(0, 1) + ->type_name("PROBE"); + +#ifdef HAS_MODERN_BPF + app.add_flag("--modern-bpf", opts.modern_bpf, + "Enable live capture using modern BPF probe"); + app.add_option("--cpus-for-each-buffer", opts.cpus_for_each_buffer, + "CPUs per syscall buffer (modern BPF only)") + ->type_name("NUM"); +#endif + + app.add_flag("--page-faults", opts.page_faults, "Capture user/kernel page faults"); + app.add_flag("--large-environment", opts.large_environment, + "Support environments larger than 4KiB"); + + // I/O options + app.add_option("-r,--read,--readfile", opts.read_files, "Read events from file") + ->type_name("FILE") + ->check(CLI::ExistingFile); + + app.add_option("-w,--write,--writefile", opts.write_file, "Write captured events to file") + ->type_name("FILE"); + + app.add_option("-s,--snaplen", opts.snaplen, "Capture first bytes of I/O buffers") + ->type_name("LEN"); + + app.add_option("-n,--numevents", opts.num_events, "Stop capturing after events") + ->type_name("NUM"); + + app.add_option("-M", opts.max_seconds, "Stop collecting after ") + ->type_name("SECONDS"); + + // File rotation options + app.add_option("-C,--file-size", opts.file_size_mb, + "Rotate capture files when they reach this size (MB)") + ->type_name("MB"); + + app.add_option("-G,--seconds", opts.duration_seconds, + "Rotate dump file every ") + ->type_name("SECONDS"); + + app.add_option("-W,--limit", opts.file_limit, + "Limit number of capture files in rotation") + ->type_name("NUM"); + + app.add_option("-e,--event-limit", opts.event_limit, + "Number of events per dump file") + ->type_name("NUM"); + + // Filter options + app.add_flag("-d,--displayflt", opts.display_filter, + "Make filter a display filter (applied after state system)"); + app.add_flag("-F,--fatfile", opts.fatfile, "Enable fatfile mode when writing"); + app.add_flag("--filter-proclist", opts.filter_proclist, + "Apply filter to /proc dump"); + + app.add_option("-U,--suppress-comm", opts.suppress_comms, + "Ignore events from processes with this comm") + ->type_name("COMM"); + + // Time format + app.add_option("-t,--timetype", opts.time_format, + "Change event time display (h=human, a=absolute, r=relative, d=delta, D=delta-previous)") + ->type_name("TYPE") + ->check(CLI::IsMember({"h", "a", "r", "d", "D"})); + + // Color output + app.add_option("--color", opts.color_mode, "Set color settings (true/false/force)") + ->type_name("MODE") + ->check(CLI::IsMember({"true", "false", "force"})); + + // Log level + app.add_option("--log-level", opts.log_level, "Select log level") + ->type_name("LEVEL") + ->check(CLI::IsMember({"trace", "debug", "info", "notice", "warning", "error", "critical", "fatal"})); + + // Plugin options + app.add_option("-H,--plugin", opts.plugins, "Register a plugin with optional init config") + ->type_name("PLUGIN[:CONFIG]"); + + app.add_option("-I,--input", opts.input_plugin, "Set plugin as input source with open params") + ->type_name("PLUGIN[:PARAMS]"); + + app.add_option("--plugin-config-file", opts.plugin_config_file, + "Load plugin configuration from file") + ->type_name("FILE") + ->check(CLI::ExistingFile); + + app.add_option("--plugin-info", opts.plugin_info, "Print info for a single plugin") + ->type_name("PLUGIN"); + + // gVisor options + app.add_option("-g,--gvisor-config", opts.gvisor_config, + "Parse events from gVisor using config file") + ->type_name("FILE") + ->check(CLI::ExistingFile); + + app.add_option("--gvisor-root", opts.gvisor_root, + "gVisor root directory for container state") + ->type_name("PATH"); + + app.add_option("--gvisor-generate-config", opts.gvisor_generate_config, + "Generate gVisor configuration file") + ->expected(0, 1) + ->type_name("SOCKET"); + + // List options + app.add_option("-l,--list", opts.list_fields_source, "List fields for filtering/output") + ->default_str("") + ->expected(0, 1) + ->type_name("SOURCE"); + + app.add_option("--list-markdown", opts.list_fields_source, "List fields in markdown format") + ->default_str("") + ->expected(0, 1) + ->type_name("SOURCE"); + + app.add_flag("-L,--list-events", opts.list_events, "List events the engine supports"); + +#ifdef HAS_CHISELS + // Chisel options + app.add_option("-c,--chisel", opts.chisels, "Run specified chisel with arguments") + ->type_name("CHISEL [ARGS]"); + + app.add_flag("-cl,--list-chisels", opts.list_chisels, "List available chisels"); + + app.add_option("-i,--chisel-info", opts.chisel_info, + "Get description and arguments for a chisel") + ->type_name("CHISEL"); +#endif + + try { + app.parse(argc, argv); + + // Handle list-fields flag specially + if(app.count("-l") || app.count("--list")) { + opts.list_fields = true; + } + if(app.count("--list-markdown")) + { + opts.list_fields_markdown = true; + opts.list_fields = true; + } + + // Collect remaining arguments as filter + opts.filter_args = app.remaining(); + + } catch(const CLI::ParseError &e) { + throw sinsp_exception(e.what()); + } + + return opts; +} + // // ARGUMENT PARSING AND PROGRAM SETUP // @@ -985,7 +1329,6 @@ sysdig_init_res sysdig_init(int argc, char **argv) std::unique_ptr dumper; std::vector infiles; std::string outfile; - int op; uint64_t cnt = -1; bool quiet = false; bool is_filter_display = false; @@ -1001,8 +1344,8 @@ sysdig_init_res sysdig_init(int argc, char **argv) captureinfo cinfo; std::string output_format; std::string output_format_plugin; + std::string filter; uint32_t snaplen = 0; - int long_index = 0; int32_t n_filterargs = 0; bool jflag = false; bool unbuf_flag = false; @@ -1012,7 +1355,6 @@ sysdig_init_res sysdig_init(int argc, char **argv) std::vector summary_table; std::set suppress_comms; plugin_utils plugins; - bool list_plugins = false; std::string plugin_config_file = ""; sinsp_opener opener; std::unique_ptr filter_list; @@ -1027,72 +1369,12 @@ sysdig_init_res sysdig_init(int argc, char **argv) int file_limit = 0; unsigned long event_limit = 0L; - static struct option long_options[] = - { - {"print-ascii", no_argument, 0, 'A' }, - {"print-base64", no_argument, 0, 'b' }, - {"bpf", optional_argument, 0, 'B' }, -#ifdef HAS_CHISELS - {"chisel", required_argument, 0, 'c' }, - {"list-chisels", no_argument, 0, 0 }, -#endif -#ifdef HAS_MODERN_BPF - {"cpus-for-each-buffer", required_argument, 0, 0 }, -#endif - {"displayflt", no_argument, 0, 'd' }, - {"debug", no_argument, 0, 'D'}, - {"exclude-users", no_argument, 0, 'E' }, - {"event-limit", required_argument, 0, 'e'}, - {"fatfile", no_argument, 0, 'F'}, - {"filter-proclist", no_argument, 0, 0 }, - {"gvisor-config", required_argument, 0, 'g'}, - {"gvisor-generate-config", optional_argument, 0, 0}, - {"gvisor-root", required_argument, 0, 0}, - {"seconds", required_argument, 0, 'G' }, - {"help", no_argument, 0, 'h' }, - {"input", required_argument, 0, 'I' }, -#ifdef HAS_CHISELS - {"chisel-info", required_argument, 0, 'i' }, -#endif - {"file-size", required_argument, 0, 'C' }, - {"json", no_argument, 0, 'j' }, - {"large-environment", no_argument, 0, 0 }, - {"list", optional_argument, 0, 'l' }, - {"list-events", no_argument, 0, 'L' }, - {"list-markdown", optional_argument, 0, 0 }, - {"libs-version", no_argument, 0, 0}, - {"log-level", required_argument, 0, 0 }, -#ifdef HAS_MODERN_BPF - {"modern-bpf", no_argument, 0, 0 }, -#endif - {"numevents", required_argument, 0, 'n' }, - {"page-faults", no_argument, 0, 0 }, - {"plugin", required_argument, 0, 'H' }, - {"plugin-config-file", required_argument, 0, 0}, - {"plugin-info", required_argument, 0, 0 }, - {"progress", required_argument, 0, 'P' }, - {"print", required_argument, 0, 'p' }, - {"quiet", no_argument, 0, 'q' }, - {"resolve-ports", no_argument, 0, 'R'}, - {"readfile", required_argument, 0, 'r' }, - {"snaplen", required_argument, 0, 's' }, - {"summary", no_argument, 0, 'S' }, - {"suppress-comm", required_argument, 0, 'U' }, - {"timetype", required_argument, 0, 't' }, - {"unbuffered", no_argument, 0, 0 }, - {"verbose", no_argument, 0, 'v' }, - {"version", no_argument, 0, 0 }, - {"writefile", required_argument, 0, 'w' }, - {"limit", required_argument, 0, 'W' }, - {"print-hex", no_argument, 0, 'x'}, - {"print-hex-ascii", no_argument, 0, 'X'}, - {"compress", no_argument, 0, 'z' }, - {"color", required_argument, 0, 0 }, - {0, 0, 0, 0} - }; - try { + auto normalized_args = normalize_sysdig_argv(argc, argv); + auto normalized_argv = argv_ptrs(normalized_args); + auto opts = parse_args_cli11((int)normalized_argv.size(), normalized_argv.data()); + inspector.reset(new sinsp()); inspector->set_hostname_and_port_resolution_mode(false); @@ -1109,495 +1391,415 @@ sysdig_init_res sysdig_init(int argc, char **argv) // Load container plugin (if available) plugins.load_container_plugin_if_available(inspector.get()); - // - // Parse the args - // - while ( - (op = getopt_long(argc, argv, - "AbB::c:C:dDEe:Fg:G:" - "hH:I:i:jlLm:M:n:Pp:qRr:Ss:t:U:vW:w:xXz", - long_options, &long_index)) != -1) + if(count_enabled_formats(opts) > 1) { - switch(op) - { - case 'A': - if(event_buffer_format != sinsp_evt::PF_NORMAL) - { - fprintf(stderr, "you cannot specify more than one output format\n"); - return sysdig_init_res(EXIT_SUCCESS); - } + fprintf(stderr, "you cannot specify more than one output format\n"); + return sysdig_init_res(EXIT_FAILURE); + } - event_buffer_format = sinsp_evt::PF_EOLS; - break; - case 'b': - if(event_buffer_format != sinsp_evt::PF_NORMAL) - { - fprintf(stderr, "you cannot specify more than one output format\n"); - return sysdig_init_res(EXIT_SUCCESS); - } + if(opts.help) + { + usage(); + return sysdig_init_res(EXIT_SUCCESS); + } - event_buffer_format = sinsp_evt::PF_BASE64; - break; - case 'B': - { - opener.bpf.enabled = true; - if(optarg) - { - opener.bpf.probe = optarg; - } - break; - } -#ifdef HAS_CHISELS - case 'c': - { - std::string chisel = optarg; - if(chisel == "l") - { - std::vector chlist; - sinsp_chisel::get_chisel_list(&chlist); - list_chisels(&chlist, true); - return sysdig_init_res(EXIT_SUCCESS); - } + if(opts.version) + { + printf("sysdig version %s\n", SYSDIG_VERSION); + return sysdig_init_res(EXIT_SUCCESS); + } - // TODO(therealbobo): add plugins filterchecks - auto filter_list = std::make_shared(); - filter_list->add_filter_check(std::make_unique(syslog_decoder)); + if(opts.libs_version) + { + printf("falcosecurity/libs version %s\n", FALCOSECURITY_LIBS_VERSION); + return sysdig_init_res(EXIT_SUCCESS); + } - for (auto plugin : inspector->m_plugin_manager->plugins()) - { - if (plugin->caps() & CAP_EXTRACTION) - { - // todo(therealbobo): manage field name conflicts - filter_list->add_filter_check(sinsp_plugin::new_filtercheck(plugin)); - } - } - auto tmp_filter_factory = std::make_shared(inspector.get(), *filter_list.get()); - sinsp_chisel* ch = new sinsp_chisel(inspector.get(), chisel, filter_list); - parse_chisel_args(ch, tmp_filter_factory, optind, argc, argv, &n_filterargs); - g_chisels.push_back(ch); - } -#endif - break; + if(opts.debug) + { + inspector->set_debug_mode(true); + inspector->set_internal_events_mode(true); + inspector->set_log_stderr(); + } - // File-size - case 'C': - rollover_mb = atoi(optarg); - if(rollover_mb <= 0) - { - throw sinsp_exception(std::string("invalid file size") + optarg); - res.m_res = EXIT_FAILURE; - goto exit; - } - break; - case 'D': - inspector->set_debug_mode(true); - inspector->set_internal_events_mode(true); - inspector->set_log_stderr(); - break; - case 'E': - inspector->set_import_users(false); - break; - case 'e': - event_limit = strtoul(optarg, NULL, 0); - if(event_limit <= 0) - { - throw sinsp_exception(std::string("invalid parameter 'number of events' ") + optarg); - res.m_res = EXIT_FAILURE; - goto exit; - } - break; - case 'F': - inspector->set_fatfile_dump_mode(true); - break; - // Number of seconds between roll-over - case 'g': - opener.gvisor.enabled = true; - if(optarg) - { - opener.gvisor.config = optarg; - } - break; - case 'G': - duration_seconds = atoi(optarg); - if(duration_seconds <= 0) - { - throw sinsp_exception(std::string("invalid duration") + optarg); - res.m_res = EXIT_FAILURE; - goto exit; - } - break; - case 'H': - { - std::string pluginname = optarg; - size_t cpos = pluginname.find(':'); - std::string pgname = pluginname; - std::string pginitconf; - // Extract init config from string if present - if(cpos != std::string::npos) - { - pgname = pluginname.substr(0, cpos); - pginitconf = pluginname.substr(cpos + 1); - } - plugins.load_plugin(inspector.get(), pgname); - plugins.config_plugin(inspector.get(), pgname, pginitconf); - break; - } - case 'I': - { - std::string inputname = optarg; - if(inputname == "l") - { - list_plugins = true; - break; - } + if(opts.exclude_users) + { + inspector->set_import_users(false); + } - size_t cpos = inputname.find(':'); - std::string pgname = inputname; - std::string pgpars; - // Extract open params from string if present - if(cpos != std::string::npos) - { - pgname = inputname.substr(0, cpos); - pgpars = inputname.substr(cpos + 1); - } - plugins.select_input_plugin(inspector.get(), filter_list.get(), pgname, pgpars); - g_plugin_input = true; - opener.plugin.enabled = true; - } - break; -#ifdef HAS_CHISELS - // --chisel-info and -i - case 'i': - { - cname = optarg; - std::vector chlist; + if(opts.resolve_ports) + { + inspector->set_hostname_and_port_resolution_mode(true); + } - sinsp_chisel::get_chisel_list(&chlist); + if(opts.large_environment) + { + inspector->set_large_envs(true); + } - for(uint32_t j = 0; j < chlist.size(); j++) - { - if(chlist[j].m_name == cname) - { - print_chisel_info(&chlist[j]); - return sysdig_init_res(EXIT_SUCCESS); - } - } + if(opts.print_ascii) + { + event_buffer_format = sinsp_evt::PF_EOLS; + } + else if(opts.print_base64) + { + event_buffer_format = sinsp_evt::PF_BASE64; + } + else if(opts.print_hex) + { + event_buffer_format = sinsp_evt::PF_HEX; + } + else if(opts.print_hex_ascii) + { + event_buffer_format = sinsp_evt::PF_HEXASCII; + } - throw sinsp_exception("chisel " + cname + " not found - use -cl to list them."); - } - break; + if(!opts.bpf_probe.empty() || std::find(normalized_args.begin(), normalized_args.end(), "-B") != normalized_args.end()) + { + opener.bpf.enabled = true; + opener.bpf.probe = opts.bpf_probe; + } + +#ifdef HAS_MODERN_BPF + if(opts.modern_bpf) + { + opener.bpf.enabled = true; + opener.bpf.modern = true; + } + if(opts.cpus_for_each_buffer != 0) + { + opener.bpf.cpus_for_each_syscall_buffer = (uint16_t)opts.cpus_for_each_buffer; + } #endif - case 'd': - is_filter_display = true; - break; - case 'j': - // - // set the json flag to 1 for now, the data format will depend from the print format parameters - // - jflag = true; - break; - case 'h': - usage(); - return sysdig_init_res(EXIT_SUCCESS); - case 'l': - list_flds = true; - if (optarg) - { - list_flds_source = optarg; - } - break; - case 'L': - // todo(jasondellaluce): support CLI for printing in markdown too - print_supported_events(inspector.get(), false); + + if(opts.page_faults) + { + opener.options.page_faults = true; + } + + if(opts.file_size_mb > 0) + { + rollover_mb = opts.file_size_mb; + } + + if(opts.file_size_mb < 0) + { + throw sinsp_exception("invalid file size" + std::to_string(opts.file_size_mb)); + } + + if(opts.event_limit > 0) + { + event_limit = opts.event_limit; + } + + if(opts.fatfile) + { + inspector->set_fatfile_dump_mode(true); + } + + if(!opts.gvisor_config.empty()) + { + opener.gvisor.enabled = true; + opener.gvisor.config = opts.gvisor_config; + } + + if(opts.duration_seconds != 0) + { + if(opts.duration_seconds <= 0) + { + throw sinsp_exception("invalid duration" + std::to_string(opts.duration_seconds)); + } + duration_seconds = opts.duration_seconds; + } + + for(const auto& pluginname : opts.plugins) + { + size_t cpos = pluginname.find(':'); + std::string pgname = pluginname; + std::string pginitconf; + if(cpos != std::string::npos) + { + pgname = pluginname.substr(0, cpos); + pginitconf = pluginname.substr(cpos + 1); + } + plugins.load_plugin(inspector.get(), pgname); + plugins.config_plugin(inspector.get(), pgname, pginitconf); + } + + if(!opts.input_plugin.empty()) + { + if(opts.input_plugin == "l") + { + plugins.print_plugin_info_list(inspector.get()); + printf("More detailed info about individual plugins can be printed with the --plugin-info option:\n"); + printf(" Detailed info about a single plugin\n"); + printf(" $ sysdig --plugin-info=dummy\n\n"); + printf(" Detailed info about a single plugin with a given configuration\n"); + printf(" $ sysdig -H dummy:'{\"jitter\":50}' --plugin-info=dummy\n\n"); return sysdig_init_res(EXIT_SUCCESS); - case 'M': - duration_to_tot = atoi(optarg); - if(duration_to_tot <= 0) - { - throw sinsp_exception(std::string("invalid duration") + optarg); - res.m_res = EXIT_FAILURE; - goto exit; - } - break; - case 'n': - try - { - cnt = sinsp_numparser::parseu64(optarg); - } - catch(...) - { - throw sinsp_exception("can't parse the -n argument, make sure it's a number"); - } + } - if(cnt <= 0) - { - throw sinsp_exception(std::string("invalid event count ") + optarg); - res.m_res = EXIT_FAILURE; - goto exit; - } - break; - case 'P': - opener.options.print_progress = true; - break; - case 'p': - if(std::string(optarg) == "p") - { - // -pp shows the default output format, useful if the user wants to tweak it. - printf("%s\n", output_format.c_str()); - return sysdig_init_res(EXIT_SUCCESS); - } - else if(std::string(optarg) == "c" || std::string(optarg) == "container") - { - output_format = "*%evt.num %evt.outputtime %evt.cpu %container.name (%container.id) %proc.name (%thread.tid:%thread.vtid) %evt.dir %evt.type %evt.info"; - output_format_plugin = "*%evt.num %evt.outputtime %evt.cpu %container.name (%container.id) %proc.name (%thread.tid:%thread.vtid) %evt.dir %evt.type %evt.info"; - } - else if(std::string(optarg) == "k" || std::string(optarg) == "kubernetes") - { - output_format = "*%evt.num %evt.outputtime %evt.cpu %k8s.pod.name (%container.id) %proc.name (%thread.tid:%thread.vtid) %evt.dir %evt.type %evt.info"; - } - else if(std::string(optarg) == "m" || std::string(optarg) == "mesos") - { - output_format = "*%evt.num %evt.outputtime %evt.cpu %mesos.task.name (%container.id) %proc.name (%thread.tid:%thread.vtid) %evt.dir %evt.type %evt.info"; - } - else - { - output_format = optarg; - output_format_plugin = optarg; - } - user_defined_format = true; + size_t cpos = opts.input_plugin.find(':'); + std::string pgname = opts.input_plugin; + std::string pgpars; + if(cpos != std::string::npos) + { + pgname = opts.input_plugin.substr(0, cpos); + pgpars = opts.input_plugin.substr(cpos + 1); + } + plugins.select_input_plugin(inspector.get(), filter_list.get(), pgname, pgpars); + g_plugin_input = true; + opener.plugin.enabled = true; + } - break; - case 'q': - quiet = true; - break; - case 'R': - inspector->set_hostname_and_port_resolution_mode(true); - break; - case 'r': - infiles.emplace_back(optarg); - break; - case 'S': - for(uint32_t j = 0; j < PPM_EVENT_MAX; j++) - { - summary_table.push_back(summary_table_entry(j, false)); - } +#ifdef HAS_CHISELS + if(opts.list_chisels) + { + std::vector chlist; + sinsp_chisel::get_chisel_list(&chlist); + list_chisels(&chlist, true); + return sysdig_init_res(EXIT_SUCCESS); + } - for(uint32_t j = 0; j < PPM_SC_MAX * 2; j++) + if(!opts.chisel_info.empty()) + { + cname = opts.chisel_info; + std::vector chlist; + sinsp_chisel::get_chisel_list(&chlist); + for(uint32_t j = 0; j < chlist.size(); j++) + { + if(chlist[j].m_name == cname) { - summary_table.push_back(summary_table_entry(j, true)); + print_chisel_info(&chlist[j]); + return sysdig_init_res(EXIT_SUCCESS); } + } + throw sinsp_exception("chisel " + cname + " not found - use -cl to list them."); + } +#endif - break; - case 's': - snaplen = atoi(optarg); - break; - case 't': - { - std::string tms(optarg); + is_filter_display = opts.display_filter; + jflag = opts.json; + list_flds = opts.list_fields; + list_flds_markdown = opts.list_fields_markdown; + if(!opts.list_fields_source.empty()) + { + list_flds_source = opts.list_fields_source; + } + unbuf_flag = opts.unbuffered; + filter_proclist_flag = opts.filter_proclist; + opener.options.print_progress = opts.print_progress; + quiet = opts.quiet; + verbose = opts.verbose; + infiles = opts.read_files; + snaplen = (uint32_t)opts.snaplen; + compress = opts.compress; + outfile = opts.write_file; + if(!outfile.empty()) + { + quiet = true; + } - if(tms == "h" || tms == "a" || tms == "r" || tms == "d" || tms == "D") - { - inspector->set_time_output_mode(tms.c_str()[0]); - } - else - { - fprintf(stderr, "invalid modifier for flag -t\n"); - return sysdig_init_res(EXIT_FAILURE); - } - } - break; - case 'U': - suppress_comms.insert(std::string(optarg)); - break; - case 'v': - verbose = true; - break; - case 'w': - outfile = optarg; - quiet = true; - break; + if(opts.summary) + { + for(uint32_t j = 0; j < PPM_EVENT_MAX; j++) + { + summary_table.push_back(summary_table_entry(j, false)); + } + for(uint32_t j = 0; j < PPM_SC_MAX * 2; j++) + { + summary_table.push_back(summary_table_entry(j, true)); + } + } - // Number of capture files to cycle through - case 'W': - file_limit = atoi(optarg); - if(file_limit <= 0) - { - throw sinsp_exception(std::string("invalid file limit") + optarg); - res.m_res = EXIT_FAILURE; - goto exit; - } - break; + if(opts.max_seconds != 0) + { + if(opts.max_seconds <= 0) + { + throw sinsp_exception("invalid duration" + std::to_string(opts.max_seconds)); + } + duration_to_tot = opts.max_seconds; + } - case 'x': - if(event_buffer_format != sinsp_evt::PF_NORMAL) - { - fprintf(stderr, "you cannot specify more than one output format\n"); - return sysdig_init_res(EXIT_FAILURE); - } + if(opts.num_events != std::numeric_limits::max()) + { + if(opts.num_events == 0) + { + throw sinsp_exception("invalid event count 0"); + } + cnt = opts.num_events; + } - event_buffer_format = sinsp_evt::PF_HEX; - break; - case 'X': - if(event_buffer_format != sinsp_evt::PF_NORMAL) - { - fprintf(stderr, "you cannot specify more than one output format\n"); - return sysdig_init_res(EXIT_FAILURE); - } + if(!opts.print_format.empty()) + { + if(opts.print_format == "p") + { + printf("%s\n", output_format.c_str()); + return sysdig_init_res(EXIT_SUCCESS); + } + else if(opts.print_format == "c" || opts.print_format == "container") + { + output_format = "*%evt.num %evt.outputtime %evt.cpu %container.name (%container.id) %proc.name (%thread.tid:%thread.vtid) %evt.dir %evt.type %evt.info"; + output_format_plugin = "*%evt.num %evt.outputtime %evt.cpu %container.name (%container.id) %proc.name (%thread.tid:%thread.vtid) %evt.dir %evt.type %evt.info"; + } + else if(opts.print_format == "k" || opts.print_format == "kubernetes") + { + output_format = "*%evt.num %evt.outputtime %evt.cpu %k8s.pod.name (%container.id) %proc.name (%thread.tid:%thread.vtid) %evt.dir %evt.type %evt.info"; + } + else if(opts.print_format == "m" || opts.print_format == "mesos") + { + output_format = "*%evt.num %evt.outputtime %evt.cpu %mesos.task.name (%container.id) %proc.name (%thread.tid:%thread.vtid) %evt.dir %evt.type %evt.info"; + } + else + { + output_format = opts.print_format; + output_format_plugin = opts.print_format; + } + user_defined_format = true; + } - event_buffer_format = sinsp_evt::PF_HEXASCII; - break; - case 'z': - compress = true; - break; - case 0: - { - std::string optname = std::string(long_options[long_index].name); - if (long_options[long_index].flag != 0) { - break; - } - if (optname == "version") { - printf("sysdig version %s\n", SYSDIG_VERSION); - return sysdig_init_res(EXIT_SUCCESS); - } - else if (optname == "libs-version") { - printf("falcosecurity/libs version %s\n", FALCOSECURITY_LIBS_VERSION); - return sysdig_init_res(EXIT_SUCCESS); - } - else if (optname == "log-level") { - if (std::string(optarg) == "fatal") { - inspector->set_min_log_severity(sinsp_logger::SEV_FATAL); - } - else if (std::string(optarg) == "critical") { - inspector->set_min_log_severity(sinsp_logger::SEV_CRITICAL); - } - else if (std::string(optarg) == "error") { - inspector->set_min_log_severity(sinsp_logger::SEV_ERROR); - } - else if (std::string(optarg) == "warning") { - inspector->set_min_log_severity(sinsp_logger::SEV_WARNING); - } - else if (std::string(optarg) == "notice") { - inspector->set_min_log_severity(sinsp_logger::SEV_NOTICE); - } - else if (std::string(optarg) == "info") { - inspector->set_min_log_severity(sinsp_logger::SEV_INFO); - } - else if (std::string(optarg) == "debug") { - inspector->set_min_log_severity(sinsp_logger::SEV_DEBUG); - } - else if (std::string(optarg) == "trace") { - inspector->set_min_log_severity(sinsp_logger::SEV_TRACE); - } else { - fprintf(stderr, "invalid log level %s\n", optarg); - return sysdig_init_res(EXIT_FAILURE); - } - libsinsp_logger()->add_stdout_log(); - } - else if (optname == "list-chisels") { - std::vector chlist; - sinsp_chisel::get_chisel_list(&chlist); - list_chisels(&chlist, true); - return sysdig_init_res(EXIT_SUCCESS); - } -#ifdef HAS_MODERN_BPF - else if(optname == "cpus-for-each-buffer") - { - opener.bpf.cpus_for_each_syscall_buffer = sinsp_numparser::parsed16(optarg); - } -#endif - else if (optname == "unbuffered") { - unbuf_flag = true; - } + for(const auto& comm : opts.suppress_comms) + { + suppress_comms.insert(comm); + } - else if (optname == "filter-proclist") { - filter_proclist_flag = true; - } + if(!opts.time_format.empty()) + { + std::string tms = opts.time_format; + if(tms == "h" || tms == "a" || tms == "r" || tms == "d" || tms == "D") + { + inspector->set_time_output_mode(tms.c_str()[0]); + } + else + { + fprintf(stderr, "invalid modifier for flag -t\n"); + return sysdig_init_res(EXIT_FAILURE); + } + } - else if (optname == "gvisor-generate-config") { - std::string socket_path; - if (optarg) - { - socket_path = std::string(optarg); - } - std::string generated_config = inspector->generate_gvisor_config(socket_path); - printf("%s", generated_config.c_str()); - return sysdig_init_res(EXIT_SUCCESS); - } + if(opts.file_limit != 0) + { + if(opts.file_limit <= 0) + { + throw sinsp_exception("invalid file limit" + std::to_string(opts.file_limit)); + } + file_limit = opts.file_limit; + } - else if (optname == "gvisor_root") - { - if (optarg) - { - opener.gvisor.root = std::string(optarg); - } - } + if(!opts.log_level.empty()) + { + if(opts.log_level == "fatal") { + inspector->set_min_log_severity(sinsp_logger::SEV_FATAL); + } else if(opts.log_level == "critical") { + inspector->set_min_log_severity(sinsp_logger::SEV_CRITICAL); + } else if(opts.log_level == "error") { + inspector->set_min_log_severity(sinsp_logger::SEV_ERROR); + } else if(opts.log_level == "warning") { + inspector->set_min_log_severity(sinsp_logger::SEV_WARNING); + } else if(opts.log_level == "notice") { + inspector->set_min_log_severity(sinsp_logger::SEV_NOTICE); + } else if(opts.log_level == "info") { + inspector->set_min_log_severity(sinsp_logger::SEV_INFO); + } else if(opts.log_level == "debug") { + inspector->set_min_log_severity(sinsp_logger::SEV_DEBUG); + } else if(opts.log_level == "trace") { + inspector->set_min_log_severity(sinsp_logger::SEV_TRACE); + } else { + fprintf(stderr, "invalid log level %s\n", opts.log_level.c_str()); + return sysdig_init_res(EXIT_FAILURE); + } + libsinsp_logger()->add_stdout_log(); + } - else if (optname == "large-environment") { - inspector->set_large_envs(true); - } + if(opts.list_events) + { + print_supported_events(inspector.get(), false); + return sysdig_init_res(EXIT_SUCCESS); + } - else if (optname == "list-markdown") { - list_flds = true; - list_flds_markdown = true; - if (optarg) - { - list_flds_source = optarg; - } - } + if(!opts.gvisor_generate_config.empty() || std::find(normalized_args.begin(), normalized_args.end(), "--gvisor-generate-config") != normalized_args.end()) + { + std::string generated_config = inspector->generate_gvisor_config(opts.gvisor_generate_config); + printf("%s", generated_config.c_str()); + return sysdig_init_res(EXIT_SUCCESS); + } -#ifdef HAS_MODERN_BPF - else if(optname == "modern-bpf") - { - opener.bpf.enabled = true; - opener.bpf.modern = true; - } -#endif + if(!opts.gvisor_root.empty()) + { + opener.gvisor.root = opts.gvisor_root; + } - else if(optname == "plugin-config-file") { - plugin_config_file = optarg; - plugins.load_plugins_from_conf_file(inspector.get(), filter_list.get(), plugin_config_file, false); - } + if(!opts.plugin_config_file.empty()) + { + plugin_config_file = opts.plugin_config_file; + plugins.load_plugins_from_conf_file(inspector.get(), filter_list.get(), plugin_config_file, false); + } - else if (optname == "page-faults") { - opener.options.page_faults = true; - } + if(!opts.plugin_info.empty()) + { + plugins.print_plugin_info(inspector.get(), filter_list.get(), opts.plugin_info); + return sysdig_init_res(EXIT_SUCCESS); + } - else if (optname == "plugin-info") - { - auto name = std::string(optarg); - plugins.print_plugin_info(inspector.get(), filter_list.get(), name); - return sysdig_init_res(EXIT_SUCCESS); - } + if(!opts.color_mode.empty()) + { + auto color_state = opts.color_mode; + if(color_state == "true") + { + color_flag = COLOR; + } + else if(color_state == "force") + { + color_flag = FORCE_COLOR; + } + else if(color_state == "false") + { + color_flag = NO_COLOR; + } + else + { + fprintf(stderr, "invalid color mode for flag --color\n"); + return sysdig_init_res(EXIT_FAILURE); + } + } - else if (optname == "color") +#ifdef HAS_CHISELS + if(!opts.chisels.empty()) + { + auto remaining_args = opts.filter_args; + auto remaining_argv = argv_ptrs(remaining_args); + int chisel_optind = 0; + for(const auto& chisel : opts.chisels) + { + int consumed_filterargs = 0; + auto tmp_chisel_filter_list = std::make_shared(); + tmp_chisel_filter_list->add_filter_check(std::make_unique(syslog_decoder)); + for(auto plugin : inspector->m_plugin_manager->plugins()) + { + if(plugin->caps() & CAP_EXTRACTION) { - auto color_state = std::string(optarg); - if (color_state == "true") - { - color_flag = COLOR; - } - else if (color_state == "force") - { - color_flag = FORCE_COLOR; - } - else if (color_state == "false") - { - color_flag = NO_COLOR; - } - else - { - fprintf(stderr, "invalid color mode for flag --color\n"); - return sysdig_init_res(EXIT_FAILURE); - } + tmp_chisel_filter_list->add_filter_check(sinsp_plugin::new_filtercheck(plugin)); } } - break; - // getopt_long : '?' for an ambiguous match or an extraneous parameter - case '?': - return sysdig_init_res(EXIT_FAILURE); - break; - default: - break; + auto tmp_filter_factory = std::make_shared(inspector.get(), *tmp_chisel_filter_list.get()); + sinsp_chisel* ch = new sinsp_chisel(inspector.get(), chisel, tmp_chisel_filter_list); + parse_chisel_args(ch, tmp_filter_factory, chisel, chisel_optind, (int)remaining_argv.size(), remaining_argv.data(), &consumed_filterargs); + chisel_optind += consumed_filterargs; + n_filterargs += consumed_filterargs; + g_chisels.push_back(ch); + } + } +#endif + + if(!opts.filter_args.empty()) + { + for(size_t j = (size_t)n_filterargs; j < opts.filter_args.size(); j++) + { + filter += opts.filter_args[j]; + if(j + 1 < opts.filter_args.size()) + { + filter += " "; + } } } @@ -1636,17 +1838,6 @@ sysdig_init_res sysdig_init(int argc, char **argv) // all plugins have been loaded and configured so now we initialize them plugins.init_loaded_plugins(inspector.get(), filter_list.get()); - if (list_plugins) - { - plugins.print_plugin_info_list(inspector.get()); - printf("More detailed info about individual plugins can be printed with the --plugin-info option:\n"); - printf(" Detailed info about a single plugin\n"); - printf(" $ sysdig --plugin-info=dummy\n\n"); - printf(" Detailed info about a single plugin with a given configuration\n"); - printf(" $ sysdig -H dummy:'{\"jitter\":50}' --plugin-info=dummy\n\n"); - return sysdig_init_res(EXIT_SUCCESS); - } - if (opener.plugin.enabled) { opener.plugin.name = plugins.input_plugin_name(); @@ -1729,39 +1920,22 @@ sysdig_init_res sysdig_init(int argc, char **argv) ch->set_filter_list(filter_list); } - std::string filter; - - // - // the filter is at the end of the command line - // - if(optind + n_filterargs < argc) + if(is_filter_display && !filter.empty()) { - for(int32_t j = optind + n_filterargs; j < argc; j++) + try { - filter += argv[j]; - if(j < argc - 1) - { - filter += " "; - } + sinsp_filter_compiler compiler(filter_factory, filter); + display_filter = compiler.compile(); } - - if(is_filter_display) + catch (sinsp_exception& e) { - try + const char* errpos = strstr(e.what(), g_unknown_field_err); + if (errpos != NULL) { - sinsp_filter_compiler compiler(filter_factory, filter); - display_filter = compiler.compile(); - } - catch (sinsp_exception& e) - { - const char* errpos = strstr(e.what(), g_unknown_field_err); - if (errpos != NULL) - { - const char* field = errpos + strlen(g_unknown_field_err); - plugins.print_field_extraction_support(inspector.get(), field); - } - throw e; + const char* field = errpos + strlen(g_unknown_field_err); + plugins.print_field_extraction_support(inspector.get(), field); } + throw e; } } @@ -2025,10 +2199,6 @@ int main(int argc, char **argv) // if(res.m_next_run_args.size() != 0) { - optind = 1; - opterr = 1; - optopt = '?'; - int newargc = (int)res.m_next_run_args.size() + 1; std::vector newargv; diff --git a/userspace/sysdig/utils/plugin_utils.cpp b/userspace/sysdig/utils/plugin_utils.cpp index e419e73a8c..8239055d81 100644 --- a/userspace/sysdig/utils/plugin_utils.cpp +++ b/userspace/sysdig/utils/plugin_utils.cpp @@ -38,7 +38,7 @@ limitations under the License. #define SHAREDOBJ_EXT ".so" #endif -static const char* err_plugin_not_found = "plugin not found, use -Il to list all the installed plugins: "; +static const char* err_plugin_not_found = "plugin not found, use -I l to list all the installed plugins: "; static const char* err_plugin_no_source_cap = "plugin does not support the event sourcing capability: "; namespace YAML {