diff --git a/builder/builder.ml b/builder/builder.ml
index f785cc1d0..6ee7358b9 100644
--- a/builder/builder.ml
+++ b/builder/builder.ml
@@ -43,7 +43,7 @@ let mode, arg,
firstboot, run,
format, gpg, hostname, install, list_long, network, output,
password_crypto, quiet, root_password,
- size, source, upload =
+ size, source, upload, wipe_logfile =
let display_version () =
let g = new G.guestfs () in
let version = g#version () in
@@ -163,6 +163,8 @@ let mode, arg,
upload := (file, dest) :: !upload
in
+ let wipe_logfile = ref false in
+
let ditto = " -\"-" in
let argspec = Arg.align [
"--attach", Arg.String attach_disk, "iso" ^ " " ^ s_"Attach data disk/ISO during install";
@@ -194,6 +196,7 @@ let mode, arg,
"-l", Arg.Unit list_mode, " " ^ s_"List available templates";
"--list", Arg.Unit list_mode, ditto;
"--long", Arg.Set list_long, ditto;
+ "--no-logfile", Arg.Set wipe_logfile, " " ^ s_"Wipe build log file";
"--long-options", Arg.Unit display_long_options, " " ^ s_"List long options";
"--network", Arg.Set network, " " ^ s_"Enable appliance network (default)";
"--no-network", Arg.Clear network, " " ^ s_"Disable appliance network";
@@ -252,6 +255,7 @@ read the man page virt-builder(1).
let size = !size in
let source = !source in
let upload = List.rev !upload in
+ let wipe_logfile = !wipe_logfile in
(* Check options. *)
let arg =
@@ -296,7 +300,7 @@ read the man page virt-builder(1).
firstboot, run,
format, gpg, hostname, install, list_long, network, output,
password_crypto, quiet, root_password,
- size, source, upload
+ size, source, upload, wipe_logfile
(* Timestamped messages in ordinary, non-debug non-quiet mode. *)
let msg fs = make_message_function ~quiet fs
@@ -635,11 +639,21 @@ let () =
| _ ->
eprintf (f_"%s: warning: root password could not be set for this type of guest\n%!") prog
+(* Based on the guest type, choose a log file location. *)
+let logfile =
+ match g#inspect_get_type root with
+ | "windows" | "dos" ->
+ if g#is_dir "/Temp" then "/Temp/builder.log" else "/builder.log"
+ | _ ->
+ if g#is_dir "/tmp" then "/tmp/builder.log" else "/builder.log"
+
(* Useful wrapper for scripts. *)
-let do_run cmd =
+let do_run ~display cmd =
(* Add a prologue to the scripts:
* - Pass environment variables through from the host.
- * - Send stdout to stderr so we capture all output in error messages.
+ * - Send stdout and stderr to a log file so we capture all output
+ * in error messages.
+ * Also catch errors and dump the log file completely on error.
*)
let env_vars =
filter_map (
@@ -650,13 +664,22 @@ let do_run cmd =
let env_vars = String.concat "\n" env_vars ^ "\n" in
let cmd = sprintf "\
-exec 1>&2
+exec >>%s 2>&1
%s
%s
-" env_vars cmd in
+" (quote logfile) env_vars cmd in
- if debug then eprintf "running: %s\n%!" cmd;
- ignore (g#sh cmd)
+ if debug then eprintf "running command:\n%s\n%!" cmd;
+ try ignore (g#sh cmd)
+ with Guestfs.Error msg ->
+ (* Cat the log file. *)
+ (try g#download logfile "/dev/stderr"
+ with exn ->
+ eprintf (f_"%s: internal error: could not display the log file: %s\n")
+ prog (Printexc.to_string exn)
+ );
+ eprintf (f_"%s: %s: command exited with an error\n") prog display;
+ exit 1
let guest_install_command packages =
let quoted_args = String.concat " " (List.map quote packages) in
@@ -689,7 +712,7 @@ let () =
msg (f_"Installing packages: %s") (String.concat " " install);
let cmd = guest_install_command install in
- do_run cmd;
+ do_run ~display:cmd cmd
)
(* Upload files. *)
@@ -729,12 +752,22 @@ let () =
| `Script script ->
msg (f_"Running: %s") script;
let cmd = read_whole_file script in
- do_run cmd
+ do_run ~display:script cmd
| `Command cmd ->
msg (f_"Running: %s") cmd;
- do_run cmd
+ do_run ~display:cmd cmd
) run
+(* Wipe the log file. *)
+let () =
+ if wipe_logfile && g#exists logfile then (
+ msg (f_"Wiping the log file");
+
+ (* Try various methods with decreasing complexity. *)
+ try g#scrub_file logfile
+ with _ -> g#rm_f logfile
+ )
+
(* Unmount everything and we're done! *)
let () =
msg (f_"Finishing off");
diff --git a/builder/virt-builder.pod b/builder/virt-builder.pod
index c6b4d1993..117ae565d 100644
--- a/builder/virt-builder.pod
+++ b/builder/virt-builder.pod
@@ -310,6 +310,14 @@ each operating system option.
See also: I<--source>, L.
+=item B<--no-logfile>
+
+Wipe C (log file from build commands) from the image
+after building is complete. If you don't want to reveal precisely how
+the image was built, use this option.
+
+See also: L.
+
=item B<--network>
=item B<--no-network>
@@ -569,6 +577,31 @@ The above command will create an C account with no password,
and force the user to set a password when they first log in. There
are other ways to manage passwords, see L for details.
+=head2 LOG FILE
+
+Scripts and package installation that runs at build time (I<--run>,
+I<--run-command>, I<--install>, but I firstboot) is logged in one
+of the following locations:
+
+=over 4
+
+=item C
+
+On Linux, BSD and other guests.
+
+=item C
+
+On Windows, DOS guests.
+
+=item C
+
+If C or C is missing.
+
+=back
+
+If you don't want the log file to appear in the final image, then
+use the I<--no-logfile> command line option.
+
=head2 INSTALLATION PROCESS
When you invoke virt-builder, installation proceeds as follows: