mirror of
https://github.com/libguestfs/libguestfs.git
synced 2026-03-21 22:53:37 +00:00
New tool: virt-log: It lists log files from within the guest.
See 'TODO' file for suggested future improvements.
This commit is contained in:
4
.gitignore
vendored
4
.gitignore
vendored
@@ -48,6 +48,7 @@ Makefile.in
|
||||
/bash/virt-filesystems
|
||||
/bash/virt-format
|
||||
/bash/virt-inspector
|
||||
/bash/virt-log
|
||||
/bash/virt-ls
|
||||
/bash/virt-sysprep
|
||||
/bash/virt-sparsify
|
||||
@@ -72,6 +73,8 @@ Makefile.in
|
||||
/cat/virt-cat.1
|
||||
/cat/virt-filesystems
|
||||
/cat/virt-filesystems.1
|
||||
/cat/virt-log
|
||||
/cat/virt-log.1
|
||||
/cat/virt-ls
|
||||
/cat/virt-ls.1
|
||||
/ChangeLog
|
||||
@@ -245,6 +248,7 @@ Makefile.in
|
||||
/html/virt-inspector.1.html
|
||||
/html/virt-list-filesystems.1.html
|
||||
/html/virt-list-partitions.1.html
|
||||
/html/virt-log.1.html
|
||||
/html/virt-ls.1.html
|
||||
/html/virt-make-fs.1.html
|
||||
/html/virt-p2v.1.html
|
||||
|
||||
8
TODO
8
TODO
@@ -590,3 +590,11 @@ Python
|
||||
|
||||
It seems as if we should call PyErr_Clear() somewhere in every
|
||||
Python binding.
|
||||
|
||||
Improvements in virt-log
|
||||
------------------------
|
||||
|
||||
- Make it faster, especially if the user wants to grep the output.
|
||||
|
||||
- Support Windows guests, see
|
||||
http://rwmj.wordpress.com/2011/04/17/decoding-the-windows-event-log-using-guestfish/
|
||||
|
||||
@@ -28,6 +28,7 @@ scripts = \
|
||||
virt-filesystems \
|
||||
virt-format \
|
||||
virt-inspector \
|
||||
virt-log \
|
||||
virt-ls \
|
||||
virt-rescue \
|
||||
virt-resize \
|
||||
@@ -51,6 +52,8 @@ virt-format:
|
||||
ln -sf virt-alignment-scan $@
|
||||
virt-inspector:
|
||||
ln -sf virt-alignment-scan $@
|
||||
virt-log:
|
||||
ln -sf virt-alignment-scan $@
|
||||
virt-ls:
|
||||
ln -sf virt-alignment-scan $@
|
||||
virt-sysprep:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# libguestfs virt-cat, virt-filesystems and virt-ls.
|
||||
# Copyright (C) 2010-2012 Red Hat Inc.
|
||||
# libguestfs virt-cat, virt-filesystems, virt-log and virt-ls.
|
||||
# Copyright (C) 2010-2014 Red Hat Inc.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@@ -22,12 +22,18 @@ EXTRA_DIST = \
|
||||
virt-cat.pod \
|
||||
test-virt-filesystems.sh \
|
||||
virt-filesystems.pod \
|
||||
test-virt-log.sh \
|
||||
virt-log.pod \
|
||||
test-virt-ls.sh \
|
||||
virt-ls.pod
|
||||
|
||||
CLEANFILES = stamp-virt-cat.pod stamp-virt-ls.pod stamp-virt-filesystems.pod
|
||||
CLEANFILES = \
|
||||
stamp-virt-cat.pod \
|
||||
stamp-virt-filesystems.pod \
|
||||
stamp-virt-log.pod \
|
||||
stamp-virt-ls.pod
|
||||
|
||||
bin_PROGRAMS = virt-cat virt-filesystems virt-ls
|
||||
bin_PROGRAMS = virt-cat virt-filesystems virt-log virt-ls
|
||||
|
||||
SHARED_SOURCE_FILES = \
|
||||
../fish/domain.c \
|
||||
@@ -82,6 +88,28 @@ virt_filesystems_LDADD = \
|
||||
$(LIBVIRT_LIBS) \
|
||||
../gnulib/lib/libgnu.la
|
||||
|
||||
virt_log_SOURCES = \
|
||||
$(SHARED_SOURCE_FILES) \
|
||||
log.c
|
||||
|
||||
virt_log_CPPFLAGS = \
|
||||
-DGUESTFS_WARN_DEPRECATED=1 \
|
||||
-DLOCALEBASEDIR=\""$(datadir)/locale"\" \
|
||||
-I$(top_srcdir)/src -I$(top_builddir)/src \
|
||||
-I$(top_srcdir)/fish \
|
||||
-I$(srcdir)/../gnulib/lib -I../gnulib/lib
|
||||
|
||||
virt_log_CFLAGS = \
|
||||
$(WARN_CFLAGS) $(WERROR_CFLAGS) \
|
||||
$(LIBXML2_CFLAGS)
|
||||
|
||||
virt_log_LDADD = \
|
||||
$(top_builddir)/src/libutils.la \
|
||||
$(top_builddir)/src/libguestfs.la \
|
||||
$(LIBXML2_LIBS) \
|
||||
$(LIBVIRT_LIBS) \
|
||||
../gnulib/lib/libgnu.la
|
||||
|
||||
virt_ls_SOURCES = \
|
||||
$(SHARED_SOURCE_FILES) \
|
||||
ls.c \
|
||||
@@ -107,11 +135,12 @@ virt_ls_LDADD = \
|
||||
../gnulib/lib/libgnu.la
|
||||
|
||||
# Manual pages and HTML files for the website.
|
||||
man_MANS = virt-cat.1 virt-filesystems.1 virt-ls.1
|
||||
man_MANS = virt-cat.1 virt-filesystems.1 virt-log.1 virt-ls.1
|
||||
|
||||
noinst_DATA = \
|
||||
$(top_builddir)/html/virt-cat.1.html \
|
||||
$(top_builddir)/html/virt-filesystems.1.html \
|
||||
$(top_builddir)/html/virt-log.1.html \
|
||||
$(top_builddir)/html/virt-ls.1.html
|
||||
|
||||
virt-cat.1 $(top_builddir)/html/virt-cat.1.html: stamp-virt-cat.pod
|
||||
@@ -124,16 +153,6 @@ stamp-virt-cat.pod: virt-cat.pod
|
||||
$<
|
||||
touch $@
|
||||
|
||||
virt-ls.1 $(top_builddir)/html/virt-ls.1.html: stamp-virt-ls.pod
|
||||
|
||||
stamp-virt-ls.pod: virt-ls.pod
|
||||
$(PODWRAPPER) \
|
||||
--man virt-ls.1 \
|
||||
--html $(top_builddir)/html/virt-ls.1.html \
|
||||
--license GPLv2+ \
|
||||
$<
|
||||
touch $@
|
||||
|
||||
virt-filesystems.1 $(top_builddir)/html/virt-filesystems.1.html: stamp-virt-filesystems.pod
|
||||
|
||||
stamp-virt-filesystems.pod: virt-filesystems.pod
|
||||
@@ -144,6 +163,26 @@ stamp-virt-filesystems.pod: virt-filesystems.pod
|
||||
$<
|
||||
touch $@
|
||||
|
||||
virt-log.1 $(top_builddir)/html/virt-log.1.html: stamp-virt-log.pod
|
||||
|
||||
stamp-virt-log.pod: virt-log.pod
|
||||
$(PODWRAPPER) \
|
||||
--man virt-log.1 \
|
||||
--html $(top_builddir)/html/virt-log.1.html \
|
||||
--license GPLv2+ \
|
||||
$<
|
||||
touch $@
|
||||
|
||||
virt-ls.1 $(top_builddir)/html/virt-ls.1.html: stamp-virt-ls.pod
|
||||
|
||||
stamp-virt-ls.pod: virt-ls.pod
|
||||
$(PODWRAPPER) \
|
||||
--man virt-ls.1 \
|
||||
--html $(top_builddir)/html/virt-ls.1.html \
|
||||
--license GPLv2+ \
|
||||
$<
|
||||
touch $@
|
||||
|
||||
# Tests.
|
||||
|
||||
TESTS_ENVIRONMENT = $(top_builddir)/run --test
|
||||
@@ -152,6 +191,7 @@ if ENABLE_APPLIANCE
|
||||
TESTS = \
|
||||
test-virt-cat.sh \
|
||||
test-virt-filesystems.sh \
|
||||
test-virt-log.sh \
|
||||
test-virt-ls.sh
|
||||
endif ENABLE_APPLIANCE
|
||||
|
||||
|
||||
398
cat/log.c
Normal file
398
cat/log.c
Normal file
@@ -0,0 +1,398 @@
|
||||
/* virt-log
|
||||
* Copyright (C) 2010-2014 Red Hat Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
#include <unistd.h>
|
||||
#include <getopt.h>
|
||||
#include <errno.h>
|
||||
#include <locale.h>
|
||||
#include <assert.h>
|
||||
#include <libintl.h>
|
||||
#include <syslog.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "c-ctype.h"
|
||||
|
||||
#include "guestfs.h"
|
||||
#include "options.h"
|
||||
|
||||
/* Currently open libguestfs handle. */
|
||||
guestfs_h *g;
|
||||
|
||||
int read_only = 1;
|
||||
int live = 0;
|
||||
int verbose = 0;
|
||||
int keys_from_stdin = 0;
|
||||
int echo_keys = 0;
|
||||
const char *libvirt_uri = NULL;
|
||||
int inspector = 1;
|
||||
|
||||
#define JOURNAL_DIR "/var/log/journal"
|
||||
|
||||
static int do_log (void);
|
||||
static int do_log_journal (void);
|
||||
static int do_log_text_file (const char *filename);
|
||||
|
||||
static void __attribute__((noreturn))
|
||||
usage (int status)
|
||||
{
|
||||
if (status != EXIT_SUCCESS)
|
||||
fprintf (stderr, _("Try `%s --help' for more information.\n"),
|
||||
program_name);
|
||||
else {
|
||||
fprintf (stdout,
|
||||
_("%s: display log files in a virtual machine\n"
|
||||
"Copyright (C) 2010-2014 Red Hat Inc.\n"
|
||||
"Usage:\n"
|
||||
" %s [--options] -d domname\n"
|
||||
" %s [--options] -a disk.img [-a disk.img ...]\n"
|
||||
"Options:\n"
|
||||
" -a|--add image Add image\n"
|
||||
" -c|--connect uri Specify libvirt URI for -d option\n"
|
||||
" -d|--domain guest Add disks from libvirt guest\n"
|
||||
" --echo-keys Don't turn off echo for passphrases\n"
|
||||
" --format[=raw|..] Force disk format for -a option\n"
|
||||
" --help Display brief help\n"
|
||||
" --keys-from-stdin Read passphrases from stdin\n"
|
||||
" -v|--verbose Verbose messages\n"
|
||||
" -V|--version Display version and exit\n"
|
||||
" -x Trace libguestfs API calls\n"
|
||||
"For more information, see the manpage %s(1).\n"),
|
||||
program_name, program_name, program_name,
|
||||
program_name);
|
||||
}
|
||||
exit (status);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
setlocale (LC_ALL, "");
|
||||
bindtextdomain (PACKAGE, LOCALEBASEDIR);
|
||||
textdomain (PACKAGE);
|
||||
|
||||
enum { HELP_OPTION = CHAR_MAX + 1 };
|
||||
|
||||
static const char *options = "a:c:d:vVx";
|
||||
static const struct option long_options[] = {
|
||||
{ "add", 1, 0, 'a' },
|
||||
{ "connect", 1, 0, 'c' },
|
||||
{ "domain", 1, 0, 'd' },
|
||||
{ "echo-keys", 0, 0, 0 },
|
||||
{ "format", 2, 0, 0 },
|
||||
{ "help", 0, 0, HELP_OPTION },
|
||||
{ "keys-from-stdin", 0, 0, 0 },
|
||||
{ "long-options", 0, 0, 0 },
|
||||
{ "verbose", 0, 0, 'v' },
|
||||
{ "version", 0, 0, 'V' },
|
||||
{ 0, 0, 0, 0 }
|
||||
};
|
||||
struct drv *drvs = NULL;
|
||||
const char *format = NULL;
|
||||
int c;
|
||||
int r;
|
||||
int option_index;
|
||||
|
||||
g = guestfs_create ();
|
||||
if (g == NULL) {
|
||||
fprintf (stderr, _("guestfs_create: failed to create handle\n"));
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
c = getopt_long (argc, argv, options, long_options, &option_index);
|
||||
if (c == -1) break;
|
||||
|
||||
switch (c) {
|
||||
case 0: /* options which are long only */
|
||||
if (STREQ (long_options[option_index].name, "long-options"))
|
||||
display_long_options (long_options);
|
||||
else if (STREQ (long_options[option_index].name, "keys-from-stdin")) {
|
||||
keys_from_stdin = 1;
|
||||
} else if (STREQ (long_options[option_index].name, "echo-keys")) {
|
||||
echo_keys = 1;
|
||||
} else if (STREQ (long_options[option_index].name, "format")) {
|
||||
if (!optarg || STREQ (optarg, ""))
|
||||
format = NULL;
|
||||
else
|
||||
format = optarg;
|
||||
} else {
|
||||
fprintf (stderr, _("%s: unknown long option: %s (%d)\n"),
|
||||
program_name, long_options[option_index].name, option_index);
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'a':
|
||||
OPTION_a;
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
OPTION_c;
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
OPTION_d;
|
||||
break;
|
||||
|
||||
case 'v':
|
||||
OPTION_v;
|
||||
break;
|
||||
|
||||
case 'V':
|
||||
OPTION_V;
|
||||
break;
|
||||
|
||||
case 'x':
|
||||
OPTION_x;
|
||||
break;
|
||||
|
||||
case HELP_OPTION:
|
||||
usage (EXIT_SUCCESS);
|
||||
|
||||
default:
|
||||
usage (EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
/* These are really constants, but they have to be variables for the
|
||||
* options parsing code. Assert here that they have known-good
|
||||
* values.
|
||||
*/
|
||||
assert (read_only == 1);
|
||||
assert (inspector == 1);
|
||||
assert (live == 0);
|
||||
|
||||
/* User must not specify more arguments on the command line. */
|
||||
if (optind != argc)
|
||||
usage (EXIT_FAILURE);
|
||||
|
||||
/* User must have specified some drives. */
|
||||
if (drvs == NULL)
|
||||
usage (EXIT_FAILURE);
|
||||
|
||||
/* Add drives, inspect and mount. Note that inspector is always true,
|
||||
* and there is no -m option.
|
||||
*/
|
||||
add_drives (drvs, 'a');
|
||||
|
||||
if (guestfs_launch (g) == -1)
|
||||
exit (EXIT_FAILURE);
|
||||
|
||||
inspect_mount ();
|
||||
|
||||
/* Free up data structures, no longer needed after this point. */
|
||||
free_drives (drvs);
|
||||
|
||||
r = do_log ();
|
||||
|
||||
guestfs_close (g);
|
||||
|
||||
exit (r == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
|
||||
}
|
||||
|
||||
static int
|
||||
do_log (void)
|
||||
{
|
||||
CLEANUP_FREE_STRING_LIST char **roots = NULL;
|
||||
char *root;
|
||||
CLEANUP_FREE char *type = NULL;
|
||||
CLEANUP_FREE_STRING_LIST char **journal_files = NULL;
|
||||
|
||||
/* Get root mountpoint. fish/inspect.c guarantees the assertions
|
||||
* below.
|
||||
*/
|
||||
roots = guestfs_inspect_get_roots (g);
|
||||
assert (roots);
|
||||
assert (roots[0] != NULL);
|
||||
assert (roots[1] == NULL);
|
||||
root = roots[0];
|
||||
|
||||
type = guestfs_inspect_get_type (g, root);
|
||||
if (!type)
|
||||
return -1;
|
||||
|
||||
/* systemd journal? */
|
||||
guestfs_push_error_handler (g, NULL, NULL);
|
||||
journal_files = guestfs_ls (g, JOURNAL_DIR);
|
||||
guestfs_pop_error_handler (g);
|
||||
if (STREQ (type, "linux") &&
|
||||
journal_files != NULL && journal_files[0] != NULL)
|
||||
return do_log_journal ();
|
||||
|
||||
/* Regular /var/log text files with different names. */
|
||||
if (STRNEQ (type, "windows")) {
|
||||
const char *logfiles[] = { "/var/log/syslog", "/var/log/messages", NULL };
|
||||
size_t i;
|
||||
|
||||
for (i = 0; logfiles[i] != NULL; ++i) {
|
||||
if (guestfs_is_file_opts (g, logfiles[i],
|
||||
GUESTFS_IS_FILE_OPTS_FOLLOWSYMLINKS, 1,
|
||||
-1) == 1)
|
||||
return do_log_text_file (logfiles[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/* Windows is not supported right now, so give an error message. */
|
||||
if (STREQ (type, "windows")) {
|
||||
fprintf (stderr,
|
||||
_("%s: Windows guests are not supported right now.\n"
|
||||
"In the meantime, try using the technique described here:\n"
|
||||
"http://rwmj.wordpress.com/2011/04/17/decoding-the-windows-event-log-using-guestfish/\n"),
|
||||
program_name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Otherwise, there are no log files. Hmm, is this right? XXX */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Find the value of the named field from the list of attributes. If
|
||||
* not found, returns NULL (not an error). If found, returns a
|
||||
* pointer to the field, and the length of the field. NOTE: The field
|
||||
* is NOT \0-terminated, so you have to print it using "%.*s".
|
||||
*
|
||||
* There may be multiple fields with the same name. In this case, the
|
||||
* function returns the first entry.
|
||||
*/
|
||||
static const char *
|
||||
get_journal_field (const struct guestfs_xattr_list *xattrs, const char *name,
|
||||
size_t *len_rtn)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < xattrs->len; ++i) {
|
||||
if (STREQ (name, xattrs->val[i].attrname)) {
|
||||
*len_rtn = xattrs->val[i].attrval_len;
|
||||
return xattrs->val[i].attrval;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL; /* not found */
|
||||
}
|
||||
|
||||
static const char *const log_level_table[] = {
|
||||
[LOG_EMERG] = "emerg",
|
||||
[LOG_ALERT] = "alert",
|
||||
[LOG_CRIT] = "crit",
|
||||
[LOG_ERR] = "err",
|
||||
[LOG_WARNING] = "warning",
|
||||
[LOG_NOTICE] = "notice",
|
||||
[LOG_INFO] = "info",
|
||||
[LOG_DEBUG] = "debug"
|
||||
};
|
||||
|
||||
static int
|
||||
do_log_journal (void)
|
||||
{
|
||||
int r;
|
||||
unsigned errors = 0;
|
||||
|
||||
if (guestfs_journal_open (g, JOURNAL_DIR) == -1)
|
||||
return -1;
|
||||
|
||||
while ((r = guestfs_journal_next (g)) > 0) {
|
||||
CLEANUP_FREE struct guestfs_xattr_list *xattrs = NULL;
|
||||
const char *priority_str, *identifier, *comm, *pid, *message;
|
||||
size_t priority_len, identifier_len, comm_len, pid_len, message_len;
|
||||
int priority = LOG_INFO;
|
||||
int64_t ts;
|
||||
|
||||
/* The question is what fields to display. We should probably
|
||||
* make this configurable, but for now use the "short" format from
|
||||
* journalctl. (XXX)
|
||||
*/
|
||||
|
||||
xattrs = guestfs_journal_get (g);
|
||||
if (xattrs == NULL)
|
||||
exit (EXIT_FAILURE);
|
||||
|
||||
ts = guestfs_journal_get_realtime_usec (g); /* error checked below */
|
||||
|
||||
priority_str = get_journal_field (xattrs, "PRIORITY", &priority_len);
|
||||
//hostname = get_journal_field (xattrs, "_HOSTNAME", &hostname_len);
|
||||
identifier = get_journal_field (xattrs, "SYSLOG_IDENTIFIER",
|
||||
&identifier_len);
|
||||
comm = get_journal_field (xattrs, "_COMM", &comm_len);
|
||||
pid = get_journal_field (xattrs, "_PID", &pid_len);
|
||||
message = get_journal_field (xattrs, "MESSAGE", &message_len);
|
||||
|
||||
/* Timestamp. */
|
||||
if (ts >= 0) {
|
||||
char buf[64];
|
||||
struct tm tm;
|
||||
|
||||
ts /= 1000000;
|
||||
if (strftime (buf, sizeof buf, "%b %d %H:%M:%S",
|
||||
localtime_r (&ts, &tm)) <= 0) {
|
||||
fprintf (stderr, _("%s: could not format journal entry timestamp\n"),
|
||||
program_name);
|
||||
errors++;
|
||||
continue;
|
||||
}
|
||||
fputs (buf, stdout);
|
||||
}
|
||||
|
||||
/* Hostname. */
|
||||
/* We don't print this because it is assumed each line from the
|
||||
* guest will have the same hostname. (XXX)
|
||||
*/
|
||||
//if (hostname)
|
||||
// printf (" %.*s", (int) hostname_len, hostname);
|
||||
|
||||
/* Identifier. */
|
||||
if (identifier)
|
||||
printf (" %.*s", (int) identifier_len, identifier);
|
||||
else if (comm)
|
||||
printf (" %.*s", (int) comm_len, comm);
|
||||
|
||||
/* PID */
|
||||
if (pid)
|
||||
printf ("[%.*s]", (int) pid_len, pid);
|
||||
|
||||
/* Log level. */
|
||||
if (priority_str && *priority_str >= '0' && *priority_str <= '7')
|
||||
priority = *priority_str - '0';
|
||||
|
||||
printf (" %s:", log_level_table[priority]);
|
||||
|
||||
/* Message. */
|
||||
if (message)
|
||||
printf (" %.*s", (int) message_len, message);
|
||||
|
||||
printf ("\n");
|
||||
}
|
||||
if (r == -1) /* error from guestfs_journal_next */
|
||||
return -1;
|
||||
|
||||
if (guestfs_journal_close (g) == -1)
|
||||
return -1;
|
||||
|
||||
return errors > 0 ? -1 : 0;
|
||||
}
|
||||
|
||||
static int
|
||||
do_log_text_file (const char *filename)
|
||||
{
|
||||
return guestfs_download (g, filename, "/dev/stdout");
|
||||
}
|
||||
25
cat/test-virt-log.sh
Executable file
25
cat/test-virt-log.sh
Executable file
@@ -0,0 +1,25 @@
|
||||
#!/bin/bash -
|
||||
# libguestfs
|
||||
# Copyright (C) 2009-2014 Red Hat Inc.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
export LANG=C
|
||||
set -e
|
||||
|
||||
# Read out the log files from the image using virt-log.
|
||||
for f in ../tests/guests/{fedora,debian,ubuntu}.img; do
|
||||
if [ -s "$f" ]; then $VG ./virt-log -a "$f"; fi
|
||||
done
|
||||
@@ -34,15 +34,6 @@ C<mydomain>:
|
||||
|
||||
virt-cat -d mydomain /etc/fstab
|
||||
|
||||
List syslog messages from a VM disk image file:
|
||||
|
||||
virt-cat -a disk.img /var/log/messages | tail
|
||||
|
||||
Find out what DHCP IP address a VM acquired:
|
||||
|
||||
virt-cat -d mydomain /var/log/messages | \
|
||||
grep 'dhclient: bound to' | tail
|
||||
|
||||
Find out what packages were recently installed:
|
||||
|
||||
virt-cat -d mydomain /var/log/yum.log | tail
|
||||
@@ -169,6 +160,12 @@ name as a guest.
|
||||
|
||||
For compatibility the old style is still supported.
|
||||
|
||||
=head1 LOG FILES
|
||||
|
||||
To list out the log files from guests, see the related tool
|
||||
L<virt-log(1)>. It understands binary log formats such as the systemd
|
||||
journal.
|
||||
|
||||
=head1 WINDOWS PATHS
|
||||
|
||||
C<virt-cat> has a limited ability to understand Windows drive letters
|
||||
@@ -250,6 +247,7 @@ L<guestfs(3)>,
|
||||
L<guestfish(1)>,
|
||||
L<virt-copy-out(1)>,
|
||||
L<virt-edit(1)>,
|
||||
L<virt-log(1)>,
|
||||
L<virt-tar-out(1)>,
|
||||
L<http://libguestfs.org/>.
|
||||
|
||||
|
||||
158
cat/virt-log.pod
Normal file
158
cat/virt-log.pod
Normal file
@@ -0,0 +1,158 @@
|
||||
=head1 NAME
|
||||
|
||||
virt-log - Display log files from a virtual machine
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
virt-log [--options] -d domname
|
||||
|
||||
virt-log [--options] -a disk.img [-a disk.img ...]
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
C<virt-log> is a command line tool to display the log files from the
|
||||
named virtual machine (or disk image).
|
||||
|
||||
This tool understands and displays both plain text log files
|
||||
(eg. C</var/log/messages>) and binary formats such as the systemd
|
||||
journal.
|
||||
|
||||
To display other types of files, use L<virt-cat(1)>. To copy files
|
||||
out of a virtual machine, use L<virt-copy-out(1)>. To display the
|
||||
contents of the Windows Registry, use L<virt-win-reg(1)>.
|
||||
|
||||
=head1 EXAMPLES
|
||||
|
||||
Display the complete logs from a guest:
|
||||
|
||||
virt-log -d mydomain | less
|
||||
|
||||
Find out what DHCP IP address a VM acquired:
|
||||
|
||||
virt-log -d mydomain | grep 'dhclient.*bound to'
|
||||
|
||||
=head1 OPTIONS
|
||||
|
||||
=over 4
|
||||
|
||||
=item B<--help>
|
||||
|
||||
Display brief help.
|
||||
|
||||
=item B<-a> file
|
||||
|
||||
=item B<--add> file
|
||||
|
||||
Add I<file> which should be a disk image from a virtual machine. If
|
||||
the virtual machine has multiple block devices, you must supply all of
|
||||
them with separate I<-a> options.
|
||||
|
||||
The format of the disk image is auto-detected. To override this and
|
||||
force a particular format use the I<--format=..> option.
|
||||
|
||||
=item B<-a URI>
|
||||
|
||||
=item B<--add URI>
|
||||
|
||||
Add a remote disk. See L<guestfish(1)/ADDING REMOTE STORAGE>.
|
||||
|
||||
=item B<-c> URI
|
||||
|
||||
=item B<--connect> URI
|
||||
|
||||
If using libvirt, connect to the given I<URI>. If omitted, then we
|
||||
connect to the default libvirt hypervisor.
|
||||
|
||||
If you specify guest block devices directly (I<-a>), then libvirt is
|
||||
not used at all.
|
||||
|
||||
=item B<-d> guest
|
||||
|
||||
=item B<--domain> guest
|
||||
|
||||
Add all the disks from the named libvirt guest. Domain UUIDs can be
|
||||
used instead of names.
|
||||
|
||||
=item B<--echo-keys>
|
||||
|
||||
When prompting for keys and passphrases, virt-log normally turns
|
||||
echoing off so you cannot see what you are typing. If you are not
|
||||
worried about Tempest attacks and there is no one else in the room you
|
||||
can specify this flag to see what you are typing.
|
||||
|
||||
=item B<--format=raw|qcow2|..>
|
||||
|
||||
=item B<--format>
|
||||
|
||||
The default for the I<-a> option is to auto-detect the format of the
|
||||
disk image. Using this forces the disk format for I<-a> options which
|
||||
follow on the command line. Using I<--format> with no argument
|
||||
switches back to auto-detection for subsequent I<-a> options.
|
||||
|
||||
For example:
|
||||
|
||||
virt-log --format=raw -a disk.img
|
||||
|
||||
forces raw format (no auto-detection) for C<disk.img>.
|
||||
|
||||
virt-log --format=raw -a disk.img --format -a another.img
|
||||
|
||||
forces raw format (no auto-detection) for C<disk.img> and reverts to
|
||||
auto-detection for C<another.img>.
|
||||
|
||||
If you have untrusted raw-format guest disk images, you should use
|
||||
this option to specify the disk format. This avoids a possible
|
||||
security problem with malicious guests (CVE-2010-3851).
|
||||
|
||||
=item B<--keys-from-stdin>
|
||||
|
||||
Read key or passphrase parameters from stdin. The default is
|
||||
to try to read passphrases from the user by opening C</dev/tty>.
|
||||
|
||||
=item B<-v>
|
||||
|
||||
=item B<--verbose>
|
||||
|
||||
Enable verbose messages for debugging.
|
||||
|
||||
=item B<-V>
|
||||
|
||||
=item B<--version>
|
||||
|
||||
Display version number and exit.
|
||||
|
||||
=item B<-x>
|
||||
|
||||
Enable tracing of libguestfs API calls.
|
||||
|
||||
=back
|
||||
|
||||
=head1 SHELL QUOTING
|
||||
|
||||
Libvirt guest names can contain arbitrary characters, some of which
|
||||
have meaning to the shell such as C<#> and space. You may need to
|
||||
quote or escape these characters on the command line. See the shell
|
||||
manual page L<sh(1)> for details.
|
||||
|
||||
=head1 EXIT STATUS
|
||||
|
||||
This program returns 0 if successful, or non-zero if there was an
|
||||
error.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
L<guestfs(3)>,
|
||||
L<guestfish(1)>,
|
||||
L<virt-cat(1)>,
|
||||
L<virt-copy-out(1)>,
|
||||
L<virt-tar-out(1)>,
|
||||
L<virt-win-reg(1)>,
|
||||
L<http://libguestfs.org/>.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Richard W.M. Jones L<http://people.redhat.com/~rjones/>
|
||||
|
||||
=head1 COPYRIGHT
|
||||
|
||||
Copyright (C) 2010-2014 Red Hat Inc.
|
||||
@@ -1615,6 +1615,7 @@ L<virt-filesystems(1)>,
|
||||
L<virt-inspector(1)>,
|
||||
L<virt-list-filesystems(1)>,
|
||||
L<virt-list-partitions(1)>,
|
||||
L<virt-log(1)>,
|
||||
L<virt-ls(1)>,
|
||||
L<virt-make-fs(1)>,
|
||||
L<virt-p2v(1)>,
|
||||
|
||||
@@ -64,6 +64,7 @@ MANPAGES = \
|
||||
virt-inspector.1 \
|
||||
virt-list-filesystems.1 \
|
||||
virt-list-partitions.1 \
|
||||
virt-log.1 \
|
||||
virt-ls.1 \
|
||||
virt-make-fs.1 \
|
||||
virt-rescue.1 \
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
../builder/virt-index-validate.pod
|
||||
../cat/virt-cat.pod
|
||||
../cat/virt-filesystems.pod
|
||||
../cat/virt-log.pod
|
||||
../cat/virt-ls.pod
|
||||
../customize/customize-options.pod
|
||||
../customize/customize-synopsis.pod
|
||||
|
||||
@@ -64,6 +64,7 @@ MANPAGES = \
|
||||
virt-inspector.1 \
|
||||
virt-list-filesystems.1 \
|
||||
virt-list-partitions.1 \
|
||||
virt-log.1 \
|
||||
virt-ls.1 \
|
||||
virt-make-fs.1 \
|
||||
virt-rescue.1 \
|
||||
|
||||
@@ -9,6 +9,7 @@ builder/setlocale-c.c
|
||||
builder/uname-c.c
|
||||
cat/cat.c
|
||||
cat/filesystems.c
|
||||
cat/log.c
|
||||
cat/ls.c
|
||||
cat/visit.c
|
||||
customize/crypt-c.c
|
||||
|
||||
@@ -4289,8 +4289,8 @@ L<virt-builder(1)> command and documentation.
|
||||
|
||||
=item C<cat>
|
||||
|
||||
The L<virt-cat(1)>, L<virt-filesystems(1)> and L<virt-ls(1)> commands
|
||||
and documentation.
|
||||
The L<virt-cat(1)>, L<virt-filesystems(1)>, L<virt-log(1)>
|
||||
and L<virt-ls(1)> commands and documentation.
|
||||
|
||||
=item C<contrib>
|
||||
|
||||
@@ -4776,6 +4776,7 @@ L<virt-format(1)>,
|
||||
L<virt-inspector(1)>,
|
||||
L<virt-list-filesystems(1)>,
|
||||
L<virt-list-partitions(1)>,
|
||||
L<virt-log(1)>,
|
||||
L<virt-ls(1)>,
|
||||
L<virt-make-fs(1)>,
|
||||
L<virt-p2v(1)>,
|
||||
|
||||
Reference in New Issue
Block a user