5 use Pod
::Usage
qw( pod2usage );
6 use Getopt
::Long
qw( :config gnu_getopt );
7 use version
; my $VERSION = qv
('0.0.1');
8 use English
qw( -no_match_vars );
12 use Net
::SSH
::Perl
::Auth
;
13 use Net
::SSH
::Perl
::Constants
qw(
14 SSH2_MSG_USERAUTH_REQUEST
15 SSH2_MSG_USERAUTH_FAILURE
16 SSH2_MSG_USERAUTH_INFO_REQUEST
17 SSH2_MSG_USERAUTH_INFO_RESPONSE );
18 use Net
::SSH
::Perl
::Auth
::KeyboardInt
;
20 use Net
::SFTP
::Attributes
;
21 use File
::Basename
qw( basename );
22 use File
::Spec
::Functions
qw( catfile );
24 # Integrated logging facility
25 use Log
::Log4perl
qw( :easy );
26 Log
::Log4perl
->easy_init($INFO);
29 username
=> 'poletti',
31 dir
=> '/tmp/our-deploy',
37 'version', 'hostname|host|h=s@',
38 'username|user|u=s', 'password|pass|p=s',
39 'debug|D!', 'dir|directory|d=s',
40 'script|s=s', 'prompt|P!',
42 pod2usage
(message
=> "$0 $VERSION", -verbose
=> 99, -sections
=> '')
44 pod2usage
(-verbose
=> 99, -sections
=> 'USAGE') if $config{usage
};
45 pod2usage
(-verbose
=> 99, -sections
=> 'USAGE|EXAMPLES|OPTIONS')
47 pod2usage
(-verbose
=> 2) if $config{man
};
49 # Script implementation here
50 $config{password
} = prompt
'password: ', -e
=> '*'
51 unless defined($config{password
}) && length($config{password
});
53 ($config{remote
} = $config{script
}) =~ s{[^\w.-]}{}mxsg;
54 $config{remote
} = catfile
($config{dir
}, $config{remote
});
56 for my $hostname (@
{$config{hostname
} || []}) {
57 eval { operate_on_host
($hostname) };
58 carp
$EVAL_ERROR if $EVAL_ERROR;
63 my $remote = $config{remote
};
65 print "*** OPERATING ON $hostname ***\n";
66 if ($config{prompt
}) {
68 lc(prompt
"$hostname - continue? (Yes | Skip | No) ",
69 -while => qr/\A[nsy]\z/mxs);
70 return if $choice eq 's';
71 exit 0 if $choice eq 'n';
72 } ## end if ($config{prompt})
74 # Transfer file into $remote
75 my $sftp = get_sftp
(get_ssh
($hostname));
76 make_path
($sftp, $config{dir
});
77 $sftp->put($config{script
}, $remote);
78 croak
"no $remote, sorry. Stopped" unless $sftp->do_stat($remote);
81 my $ssh = get_ssh
($hostname);
84 my ($out, $err, $exit) = $ssh->cmd($remote);
85 print "exit = $exit\n";
86 for ([STDOUT
=> $out], [STDERR
=> $err]) {
87 my ($type, $val) = @
$_;
88 next unless defined $val;
91 print "+ $type\n|\n$val\n|\n+ end of $type\n\n";
92 } ## end for ([STDOUT => $out], ...
94 } ## end sub operate_on_host
97 my ($sftp, $fullpath) = @_;
100 for my $chunk (split m{/}mxs, $fullpath) {
101 $path .= $chunk . '/'; # works fine with the root
102 next if $sftp->do_stat($path);
103 $sftp->do_mkdir($path, Net
::SFTP
::Attributes
->new());
105 croak
"no $path, sorry. Stopped" unless $sftp->do_stat($path);
108 } ## end sub make_path
112 my $ssh = Net
::SSH
::Perl
->new(
115 debug
=> $config{debug
}
117 $ssh->config->set(interactive
=> 1); # false!!!
118 $ssh->config->set(identity_files
=> []); # avoid 'em
119 $ssh->login($config{username
}, $config{password
}, 'suppress_shell');
125 return Net
::SFTP
::Mine
->new(
130 } ## end sub get_sftp
135 sub Net
::SSH
::Perl
::Auth
::KeyboardInt
::authenticate
{
137 my $ssh = $auth->{ssh
};
140 $packet = $ssh->packet_start(SSH2_MSG_USERAUTH_REQUEST
);
141 $packet->put_str($ssh->config->get('user'));
142 $packet->put_str("ssh-connection");
143 $packet->put_str("keyboard-interactive");
144 $packet->put_str(""); ## language
145 $packet->put_str(""); ## devices
148 $auth->mgr->register_handler(SSH2_MSG_USERAUTH_INFO_REQUEST
,
152 my $name = $packet->get_str;
153 my $instructions = $packet->get_str;
154 $packet->get_str; ## language
156 my $prompts = $packet->get_int32;
157 my $pres = $ssh->packet_start(SSH2_MSG_USERAUTH_INFO_RESPONSE
);
158 $pres->put_int32($prompts);
159 $pres->put_str($ssh->config->get('pass')) if $prompts;
165 } ## end sub Net::SSH::Perl::Auth::KeyboardInt::authenticate
168 package Net
::SFTP
::Mine
;
169 use base
qw( Net::SFTP );
170 use Net
::SSH
::Perl
::Constants
qw( :msg2 );
171 use Net
::SFTP
::Constants
172 qw( :fxp :flags :status :att SSH2_FILEXFER_VERSION );
178 $sftp->{debug
} = delete $param{debug
};
179 $sftp->{status
} = SSH2_FX_OK
;
181 $param{warn} = 1 if not defined $param{warn}; # default
182 $sftp->{warn_h
} = delete $param{warn} || sub { }; # false => ignore
183 $sftp->{warn_h
} = sub { carp
$_[1] } # true => emit warning
184 if $sftp->{warn_h
} and not ref $sftp->{warn_h
};
186 $sftp->{_msg_id
} = 0;
188 $sftp->{ssh
} = delete $param{ssh
};
190 my $channel = $sftp->_open_channel;
191 $sftp->{channel
} = $channel;
202 deploy - [Una riga di descrizione dello scopo dello script]
207 See version at beginning of script, variable $VERSION, or call
209 shell$ deploy --version
214 deploy [--usage] [--help] [--man] [--version]
221 =for l'autore, da riempire:
222 Qualche breve esempio con codice che mostri l'utilizzo più comune.
223 Questa sezione sarà quella probabilmente più letta, perché molti
224 utenti si annoiano a leggere tutta la documentazione, per cui
225 è meglio essere il più educativi ed esplicativi possibile.
230 =for l'autore, da riempire:
231 Fornite una descrizione completa del modulo e delle sue caratteristiche.
232 Aiutatevi a strutturare il testo con le sottosezioni (=head2, =head3)
238 =for l'autore, da riempire:
239 Una descrizione di tutte le opzioni possibili nella chiamata allo script
245 print a somewhat more verbose help, showing usage, this description of
246 the options and some examples from the synopsis.
250 print out the full documentation for the script.
254 print a concise usage line and exit.
258 print the version of the script.
264 =for l'autore, da riempire:
265 Elencate qualunque singolo errore o messaggio di avvertimento che
266 lo script può generare, anche quelli che non "accadranno mai".
267 Includete anche una spiegazione completa di ciascuno di questi
268 problemi, una o più possibili cause e qualunque rimedio
274 =item C<< Error message here, perhaps with %s placeholders >>
276 [Descrizione di un errore]
278 =item C<< Another error message here >>
280 [Descrizione di un errore]
287 =head1 CONFIGURATION AND ENVIRONMENT
289 =for l'autore, da riempire:
290 Una spiegazione completa di qualunque sistema di configurazione
291 utilizzato dallo script, inclusi i nomi e le posizioni dei file di
292 configurazione, il significato di ciascuna variabile di ambiente
293 utilizzata e proprietà che può essere impostata. Queste descrizioni
294 devono anche includere dettagli su eventuali linguaggi di configurazione
297 deploy requires no configuration files or environment variables.
302 =for l'autore, da riempire:
303 Una lista di tutti i moduli su cui si basa questo script,
304 incluse eventuali restrizioni sulle relative versioni, ed una
305 indicazione se il modulo in questione è parte della distribuzione
306 standard di Perl, parte della distribuzione del modulo o se
307 deve essere installato separatamente.
312 =head1 BUGS AND LIMITATIONS
314 =for l'autore, da riempire:
315 Una lista di tutti i problemi conosciuti relativi al modulo,
316 insime a qualche indicazione sul fatto che tali problemi siano
317 plausibilmente risolti in una versione successiva. Includete anche
318 una lista delle restrizioni sulle funzionalità fornite dal
319 modulo: tipi di dati che non si è in grado di gestire, problematiche
320 relative all'efficienza e le circostanze nelle quali queste possono
321 sorgere, limitazioni pratiche sugli insiemi dei dati, casi
322 particolari che non sono (ancora) gestiti, e così via.
324 No bugs have been reported.
326 Please report any bugs or feature requests through http://rt.cpan.org/
331 Flavio Poletti C<flavio@polettix.it>
334 =head1 LICENCE AND COPYRIGHT
336 Copyright (c) 2006, Flavio Poletti C<flavio@polettix.it>. All rights reserved.
338 This script is free software; you can redistribute it and/or
339 modify it under the same terms as Perl itself. See L<perlartistic>
342 Questo script è software libero: potete ridistribuirlo e/o
343 modificarlo negli stessi termini di Perl stesso. Vedete anche
344 L<perlartistic> e L<perlgpl>.
347 =head1 DISCLAIMER OF WARRANTY
349 BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
350 FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
351 OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
352 PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
353 EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
354 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
355 ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH
356 YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
357 NECESSARY SERVICING, REPAIR, OR CORRECTION.
359 IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
360 WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
361 REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENCE, BE
362 LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL,
363 OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE
364 THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
365 RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
366 FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
367 SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
370 =head1 NEGAZIONE DELLA GARANZIA
372 Poiché questo software viene dato con una licenza gratuita, non
373 c'è alcuna garanzia associata ad esso, ai fini e per quanto permesso
374 dalle leggi applicabili. A meno di quanto possa essere specificato
375 altrove, il proprietario e detentore del copyright fornisce questo
376 software "così com'è" senza garanzia di alcun tipo, sia essa espressa
377 o implicita, includendo fra l'altro (senza però limitarsi a questo)
378 eventuali garanzie implicite di commerciabilità e adeguatezza per
379 uno scopo particolare. L'intero rischio riguardo alla qualità ed
380 alle prestazioni di questo software rimane a voi. Se il software
381 dovesse dimostrarsi difettoso, vi assumete tutte le responsabilità
382 ed i costi per tutti i necessari servizi, riparazioni o correzioni.
384 In nessun caso, a meno che ciò non sia richiesto dalle leggi vigenti
385 o sia regolato da un accordo scritto, alcuno dei detentori del diritto
386 di copyright, o qualunque altra parte che possa modificare, o redistribuire
387 questo software così come consentito dalla licenza di cui sopra, potrà
388 essere considerato responsabile nei vostri confronti per danni, ivi
389 inclusi danni generali, speciali, incidentali o conseguenziali, derivanti
390 dall'utilizzo o dall'incapacità di utilizzo di questo software. Ciò
391 include, a puro titolo di esempio e senza limitarsi ad essi, la perdita
392 di dati, l'alterazione involontaria o indesiderata di dati, le perdite
393 sostenute da voi o da terze parti o un fallimento del software ad
394 operare con un qualsivoglia altro software. Tale negazione di garanzia
395 rimane in essere anche se i dententori del copyright, o qualsiasi altra
396 parte, è stata avvisata della possibilità di tali danneggiamenti.
398 Se decidete di utilizzare questo software, lo fate a vostro rischio
399 e pericolo. Se pensate che i termini di questa negazione di garanzia
400 non si confacciano alle vostre esigenze, o al vostro modo di
401 considerare un software, o ancora al modo in cui avete sempre trattato
402 software di terze parti, non usatelo. Se lo usate, accettate espressamente
403 questa negazione di garanzia e la piena responsabilità per qualsiasi
404 tipo di danno, di qualsiasi natura, possa derivarne.