]>
git.proxmox.com Git - pve-installer.git/blob - Proxmox/Sys/Command.pm
1 package Proxmox
::Sys
::Command
;
7 use Gtk3
qw(); # FIXME: drop once possible (when (G)UI plugin approacg is there)
11 use String
::ShellQuote
;
13 use Proxmox
::Install
::ISOEnv
;
16 use base
qw(Exporter);
17 our @EXPORT_OK = qw(run_command syscmd);
21 return String
::ShellQuote
::shell_quote
($str);
27 die "no arguments" if !$cmd;
28 return $cmd if !ref($cmd);
30 my $quoted_args = [ map { shellquote
($_) } $cmd->@* ];
32 return join (' ', $quoted_args->@*);
38 return run_command
($cmd, undef, undef, 1);
42 my ($cmd, $func, $input, $noout) = @_;
48 # see 'man bash' for option pipefail
49 $cmd = [ '/bin/bash', '-c', "set -o pipefail && $cmd" ];
54 $cmdstr = cmd2string
($cmd);
58 if ($input && ($cmdstr !~ m/chpasswd/)) {
59 $cmdtxt = "# $cmdstr <<EOD\n$input";
63 $cmdtxt = "# $cmdstr\n";
72 my ($reader, $writer, $error) = (IO
::File-
>new(), IO
::File-
>new(), IO
::File-
>new());
76 my $pid = eval { open3
($writer, $reader, $error, @$cmd) || die $!; };
79 if ($orig_pid != $$) { # catch exec errors
85 print $writer $input if defined $input;
88 my $select = IO
::Select-
>new();
89 $select->add($reader);
92 my ($ostream, $logout) = ('', '', '');
94 while ($select->count) {
95 my @handles = $select->can_read (0.2);
97 Gtk3
::main_iteration
() while Gtk3
::events_pending
();
99 next if !scalar (@handles); # timeout
101 foreach my $h (@handles) {
103 my $count = sysread ($h, $buf, 4096);
104 if (!defined ($count)) {
108 die "command '$cmd' failed: $err";
110 $select->remove($h) if !$count;
112 $ostream .= $buf if !($noout || $func);
114 while ($logout =~ s/^([^\010\r\n]*)(\r|\n|(\010)+|\r\n)//s) {
116 $func->($line) if $func;
119 } elsif ($h eq $error) {
120 $ostream .= $buf if !($noout || $func);
128 &$func($logout) if $func;
130 my $rv = waitpid ($pid, 0);
132 return $? if $noout; # behave like standard system();
135 croak
"command '$cmdstr' failed to execute\n";
136 } elsif (my $sig = ($? & 127)) {
137 croak
"command '$cmdstr' failed - got signal $sig\n";
138 } elsif (my $exitcode = ($? >> 8)) {
139 croak
"command '$cmdstr' failed with exit code $exitcode";
145 # forks and runs the provided coderef in the child
146 # do not use syscmd or run_command as both confuse the GTK mainloop if
147 # run from a child process
148 sub run_in_background
{
151 my $pid = fork() // die "fork failed: $!\n";
155 warn "run_in_background error: $err\n";