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: