1Sysadm::Install(3) User Contributed Perl Documentation Sysadm::Install(3)
2
3
4
6 Sysadm::Install - Typical installation tasks for system administrators
7
9 use Sysadm::Install qw(:all);
10
11 my $INST_DIR = '/home/me/install/';
12
13 cd($INST_DIR);
14 cp("/deliver/someproj.tgz", ".");
15 untar("someproj.tgz");
16 cd("someproj");
17
18 # Write out ...
19 blurt("Builder: Mike\nDate: Today\n", "build.dat");
20
21 # Slurp back in ...
22 my $data = slurp("build.dat");
23
24 # or edit in place ...
25 pie(sub { s/Today/scalar localtime()/ge; $_; }, "build.dat");
26
27 make("test install");
28
29 # run a cmd and tap into stdout and stderr
30 my($stdout, $stderr, $exit_code) = tap("ls", "-R");
31
33 Have you ever wished for your installation shell scripts to run
34 reproducibly, without much programming fuzz, and even with optional
35 logging enabled? Then give up shell programming, use Perl.
36
37 "Sysadm::Install" executes shell-like commands performing typical
38 installation tasks: Copying files, extracting tarballs, calling "make".
39 It has a "fail once and die" policy, meticulously checking the result
40 of every operation and calling "die()" immediately if anything fails.
41
42 "Sysadm::Install" also supports a dry_run mode, in which it logs
43 everything, but suppresses any write actions. Dry run mode is enabled
44 by calling Sysadm::Install::dry_run(1). To switch back to normal, call
45 Sysadm::Install::dry_run(0).
46
47 As of version 0.17, "Sysadm::Install" supports a confirm mode, in which
48 it interactively asks the user before running any of its functions
49 (just like "rm -i"). confirm mode is enabled by calling
50 Sysadm::Install::confirm(1). To switch back to normal, call
51 Sysadm::Install::confirm(0).
52
53 "Sysadm::Install" is fully Log4perl-enabled. To start logging, just
54 initialize "Log::Log4perl". "Sysadm::Install" acts as a wrapper class,
55 meaning that file names and line numbers are reported from the calling
56 program's point of view.
57
58 FUNCTIONS
59 "cp($source, $target)"
60 Copy a file from $source to $target. "target" can be a directory.
61 Note that "cp" doesn't copy file permissions. If you want the
62 target file to reflect the source file's user rights, use
63 "perm_cp()" shown below.
64
65 "mv($source, $target)"
66 Move a file from $source to $target. "target" can be a directory.
67
68 "download($url)"
69 Download a file specified by $url and store it under the name
70 returned by "basename($url)".
71
72 "untar($tarball)"
73 Untar the tarball in $tarball, which typically adheres to the
74 "someproject-X.XX.tgz" convention. But regardless of whether the
75 archive actually contains a top directory "someproject-X.XX", this
76 function will behave if it had one. If it doesn't have one, a new
77 directory is created before the unpacking takes place. Unpacks the
78 tarball into the current directory, no matter where the tarfile is
79 located. Please note that if you're using a compressed tarball
80 (.tar.gz or .tgz), you'll need IO::Zlib installed.
81
82 "untar_in($tar_file, $dir)"
83 Untar the tarball in $tgz_file in directory $dir. Create $dir if it
84 doesn't exist yet.
85
86 "pick($prompt, $options, $default, $opts)"
87 Ask the user to pick an item from a displayed list. $prompt is the
88 text displayed, $options is a referenc to an array of choices, and
89 $default is the number (starting from 1, not 0) of the default
90 item. For example,
91
92 pick("Pick a fruit", ["apple", "pear", "pineapple"], 3);
93
94 will display the following:
95
96 [1] apple
97 [2] pear
98 [3] pineapple
99 Pick a fruit [3]>
100
101 If the user just hits Enter, "pineapple" (the default value) will
102 be returned. Note that 3 marks the 3rd element of the list, and is
103 not an index value into the array.
104
105 If the user enters 1, 2 or 3, the corresponding text string
106 ("apple", "pear", "pineapple" will be returned by "pick()".
107
108 If the optional $opts hash has "{ tty => 1 }" set, then the user
109 response will be expected from the console, not STDIN.
110
111 "ask($prompt, $default, $opts)"
112 Ask the user to either hit Enter and select the displayed default
113 or to type in another string.
114
115 If the optional $opts hash has "{ tty => 1 }" set, then the user
116 response will be expected from the console, not STDIN.
117
118 "mkd($dir)"
119 Create a directory of arbitrary depth, just like
120 "File::Path::mkpath".
121
122 "rmf($dir)"
123 Delete a directory and all of its descendents, just like "rm -rf"
124 in the shell.
125
126 "cd($dir)"
127 chdir to the given directory. If you don't want to have cd() modify
128 the internal directory stack (used for subsequent cdback() calls),
129 set the stack_update parameter to a false value:
130
131 cd($dir, {stack_update => 0});
132
133 "cdback()"
134 chdir back to the last directory before a previous "cd". If the
135 option "reset" is set, it goes all the way back to the beginning of
136 the directory stack, i.e. no matter how many cd() calls were made
137 in between, it'll go back to the original directory:
138
139 # go all the way back
140 cdback( { reset => 1 } );
141
142 "make()"
143 Call "make" in the shell.
144
145 "pie($coderef, $filename, ...)"
146 Simulate "perl -pie 'do something' file". Edits files in-place.
147 Expects a reference to a subroutine as its first argument. It will
148 read out the file $filename line by line and calls the subroutine
149 setting a localized $_ to the current line. The return value of the
150 subroutine will replace the previous value of the line.
151
152 Example:
153
154 # Replace all 'foo's by 'bar' in test.dat
155 pie(sub { s/foo/bar/g; $_; }, "test.dat");
156
157 Works with one or more file names.
158
159 If the files are known to contain UTF-8 encoded data, and you want
160 it to be read/written as a Unicode strings, use the "utf8" option:
161
162 pie(sub { s/foo/bar/g; $_; }, "test.dat", { utf8 => 1 });
163
164 "plough($coderef, $filename, ...)"
165 Simulate "perl -ne 'do something' file". Iterates over all lines of
166 all input files and calls the subroutine provided as the first
167 argument.
168
169 Example:
170
171 # Print all lines containing 'foobar'
172 plough(sub { print if /foobar/ }, "test.dat");
173
174 Works with one or more file names.
175
176 If the files are known to contain UTF-8 encoded data, and you want
177 it to be read into Unicode strings, use the "utf8" option:
178
179 plough(sub { print if /foobar/ }, "test.dat", { utf8 => 1 });
180
181 "my $data = slurp($file, $options)"
182 Slurps in the file and returns a scalar with the file's content. If
183 called without argument, data is slurped from STDIN or from any
184 files provided on the command line (like <> operates).
185
186 If the file is known to contain UTF-8 encoded data and you want to
187 read it in as a Unicode string, use the "utf8" option:
188
189 my $unicode_string = slurp( $file, {utf8 => 1} );
190
191 "blurt($data, $file, $options)"
192 Opens a new file, prints the data in $data to it and closes the
193 file. If "$options->{append}" is set to a true value, data will be
194 appended to the file. Default is false, existing files will be
195 overwritten.
196
197 If the string is a Unicode string, use the "utf8" option:
198
199 blurt( $unicode_string, $file, {utf8 => 1} );
200
201 "blurt_atomic($data, $file, $options)"
202 Write the data in $data to a file $file, guaranteeing that the
203 operation will either complete fully or not at all. This is
204 accomplished by first writing to a temporary file which is then
205 rename()ed to the target file.
206
207 Unlike in "blurt", there is no $append mode in "blurt_atomic".
208
209 If the string is a Unicode string, use the "utf8" option:
210
211 blurt_atomic( $unicode_string, $file, {utf8 => 1} );
212
213 "($stdout, $stderr, $exit_code) = tap($cmd, @args)"
214 Run a command $cmd in the shell, and pass it @args as args.
215 Capture STDOUT and STDERR, and return them as strings. If
216 $exit_code is 0, the command succeeded. If it is different, the
217 command failed and $exit_code holds its exit code.
218
219 Please note that "tap()" is limited to single shell commands, it
220 won't work with output redirectors ("ls >/tmp/foo" 2>&1).
221
222 In default mode, "tap()" will concatenate the command and args
223 given and create a shell command line by redirecting STDERR to a
224 temporary file. "tap("ls", "/tmp")", for example, will result in
225
226 'ls' '/tmp' 2>/tmp/sometempfile |
227
228 Note that all commands are protected by single quotes to make sure
229 arguments containing spaces are processed as singles, and no
230 globbing happens on wildcards. Arguments containing single quotes
231 or backslashes are escaped properly.
232
233 If quoting is undesirable, "tap()" accepts an option hash as its
234 first parameter,
235
236 tap({no_quotes => 1}, "ls", "/tmp/*");
237
238 which will suppress any quoting:
239
240 ls /tmp/* 2>/tmp/sometempfile |
241
242 Or, if you prefer double quotes, use
243
244 tap({double_quotes => 1}, "ls", "/tmp/$VAR");
245
246 wrapping all args so that shell variables are interpolated
247 properly:
248
249 "ls" "/tmp/$VAR" 2>/tmp/sometempfile |
250
251 Another option is "utf8" which runs the command in a terminal set
252 to UTF8.
253
254 Error handling: By default, tap() won't raise an error if the
255 command's return code is nonzero, indicating an error reported by
256 the shell. If bailing out on errors is requested to avoid return
257 code checking by the script, use the raise_error option:
258
259 tap({raise_error => 1}, "ls", "doesn't exist");
260
261 In DEBUG mode, "tap" logs the entire stdout/stderr output, which
262 can get too verbose at times. To limit the number of bytes logged,
263 use the "stdout_limit" and "stderr_limit" options
264
265 tap({stdout_limit => 10}, "echo", "123456789101112");
266
267 "$quoted_string = qquote($string, [$metachars])"
268 Put a string in double quotes and escape all sensitive characters
269 so there's no unwanted interpolation. E.g., if you have something
270 like
271
272 print "foo!\n";
273
274 and want to put it into a double-quoted string, it will look like
275
276 "print \"foo!\\n\""
277
278 Sometimes, not only backslashes and double quotes need to be
279 escaped, but also the target environment's meta chars. A string
280 containing
281
282 print "$<\n";
283
284 needs to have the '$' escaped like
285
286 "print \"\$<\\n\";"
287
288 if you want to reuse it later in a shell context:
289
290 $ perl -le "print \"\$<\\n\";"
291 1212
292
293 "qquote()" supports escaping these extra characters with its
294 second, optional argument, consisting of a string listing all
295 escapable characters:
296
297 my $script = 'print "$< rocks!\\n";';
298 my $escaped = qquote($script, '!$'); # Escape for shell use
299 system("perl -e $escaped");
300
301 => 1212 rocks!
302
303 And there's a shortcut for shells: By specifying ':shell' as the
304 metacharacters string, qquote() will actually use '!$`'.
305
306 For example, if you wanted to run the perl code
307
308 print "foobar\n";
309
310 via
311
312 perl -e ...
313
314 on a box via ssh, you would use
315
316 use Sysadm::Install qw(qquote);
317
318 my $cmd = 'print "foobar!\n"';
319 $cmd = "perl -e " . qquote($cmd, ':shell');
320 $cmd = "ssh somehost " . qquote($cmd, ':shell');
321
322 print "$cmd\n";
323 system($cmd);
324
325 and get
326
327 ssh somehost "perl -e \"print \\\"foobar\\\!\\\\n\\\"\""
328
329 which runs on "somehost" without hickup and prints "foobar!".
330
331 Sysadm::Install comes with a script "one-liner" (installed in bin),
332 which takes arbitrary perl code on STDIN and transforms it into a
333 one-liner:
334
335 $ one-liner
336 Type perl code, terminate by CTRL-D
337 print "hello\n";
338 print "world\n";
339 ^D
340 perl -e "print \"hello\\n\"; print \"world\\n\"; "
341
342 "$quoted_string = quote($string, [$metachars])"
343 Similar to "qquote()", just puts a string in single quotes and
344 escapes what needs to be escaped.
345
346 Note that shells typically don't support escaped single quotes
347 within single quotes, which means that
348
349 $ echo 'foo\'bar'
350 >
351
352 is invalid and the shell waits until it finds a closing quote.
353 Instead, there is an evil trick which gives the desired result:
354
355 $ echo 'foo'\''bar' # foo, single quote, \, 2 x single quote, bar
356 foo'bar
357
358 It uses the fact that shells interpret back-to-back strings as one.
359 The construct above consists of three back-to-back strings:
360
361 (1) 'foo'
362 (2) '
363 (3) 'bar'
364
365 which all get concatenated to a single
366
367 foo'bar
368
369 If you call "quote()" with $metachars set to ":shell", it will
370 perform that magic behind the scenes:
371
372 print quote("foo'bar");
373 # prints: 'foo'\''bar'
374
375 "perm_cp($src, $dst, ...)"
376 Read the $src file's user permissions and modify all $dst files to
377 reflect the same permissions.
378
379 "owner_cp($src, $dst, ...)"
380 Read the $src file/directory's owner uid and group gid and apply it
381 to $dst.
382
383 For example: copy uid/gid of the containing directory to a file
384 therein:
385
386 use File::Basename;
387
388 owner_cp( dirname($file), $file );
389
390 Usually requires root privileges, just like chown does.
391
392 "$perms = perm_get($filename)"
393 Read the $filename's user permissions and owner/group. Returns an
394 array ref to be used later when calling "perm_set($filename,
395 $perms)".
396
397 "perm_set($filename, $perms)"
398 Set file permissions and owner of $filename according to $perms,
399 which was previously acquired by calling "perm_get($filename)".
400
401 "sysrun($cmd)"
402 Run a shell command via "system()" and die() if it fails. Also
403 works with a list of arguments, which are then interpreted as
404 program name plus arguments, just like "system()" does it.
405
406 "hammer($cmd, $arg, ...)"
407 Run a command in the shell and simulate a user hammering the ENTER
408 key to accept defaults on prompts.
409
410 "say($text, ...)"
411 Alias for "print ..., "\n"", just like Perl6 is going to provide
412 it.
413
414 "sudo_me()"
415 Check if the current script is running as root. If yes, continue.
416 If not, restart the current script with all command line arguments
417 is restarted under sudo:
418
419 sudo scriptname args ...
420
421 Make sure to call this before any @ARGV-modifying functions like
422 "getopts()" have kicked in.
423
424 "bin_find($program)"
425 Search all directories in $PATH (the ENV variable) for an
426 executable named $program and return the full path of the first
427 hit. Returns "undef" if the program can't be found.
428
429 "fs_read_open($dir)"
430 Opens a file handle to read the output of the following process:
431
432 cd $dir; find ./ -xdev -print0 | cpio -o0 |
433
434 This can be used to capture a file system structure.
435
436 "fs_write_open($dir)"
437 Opens a file handle to write to a
438
439 | (cd $dir; cpio -i0)
440
441 process to restore a file system structure. To be used in
442 conjunction with fs_read_open.
443
444 "pipe_copy($in, $out, [$bufsize])"
445 Reads from $in and writes to $out, using sysread and syswrite. The
446 buffer size used defaults to 4096, but can be set explicitly.
447
448 "snip($data, $maxlen)"
449 Format the data string in $data so that it's only (roughly) $maxlen
450 characters long and only contains printable characters.
451
452 If $data is longer than $maxlen, it will be formatted like
453
454 (22)[abcdef[snip=11]stuvw]
455
456 indicating the length of the original string, the beginning, the
457 end, and the number of 'snipped' characters.
458
459 If $data is shorter than $maxlen, it will be returned unmodified
460 (except for unprintable characters replaced, see below).
461
462 If $data contains unprintable character's they are replaced by "."
463 (the dot).
464
465 "password_read($prompt, $opts)"
466 Reads in a password to be typed in by the user in noecho mode. A
467 call to password_read("password: ") results in
468
469 password: ***** (stars aren't actually displayed)
470
471 This function will switch the terminal back into normal mode after
472 the user hits the 'Return' key.
473
474 If the optional $opts hash has "{ tty => 1 }" set, then the prompt
475 will be redirected to the console instead of STDOUT.
476
477 "nice_time($time)"
478 Format the time in a human-readable way, less wasteful than the
479 'scalar localtime' formatting.
480
481 print nice_time(), "\n";
482 # 2007/04/01 10:51:24
483
484 It uses the system time by default, but it can also accept epoch
485 seconds:
486
487 print nice_time(1170000000), "\n";
488 # 2007/01/28 08:00:00
489
490 It uses localtime() under the hood, so the outcome of the above
491 will depend on your local time zone setting.
492
493 "def_or($foo, $default)"
494 Perl-5.9 added the //= construct, which helps assigning values to
495 undefined variables. Instead of writing
496
497 if(!defined $foo) {
498 $foo = $default;
499 }
500
501 you can just write
502
503 $foo //= $default;
504
505 However, this is not available on older perl versions (although
506 there's source filter solutions). Often, people use
507
508 $foo ||= $default;
509
510 instead which is wrong if $foo contains a value that evaluates as
511 false. So Sysadm::Install, the everything-and-the-kitchen-sink
512 under the CPAN modules, provides the function "def_or()" which can
513 be used like
514
515 def_or($foo, $default);
516
517 to accomplish the same as
518
519 $foo //= $default;
520
521 How does it work, how does $foo get a different value, although
522 it's apparently passed in by value? Modifying $_[0] within the
523 subroutine is an old Perl trick to do exactly that.
524
525 "is_utf8_data($data)"
526 Check if the given string has the utf8 flag turned on. Works just
527 like Encode.pm's is_utf8() function, except that it silently
528 returns a false if Encode isn't available, for example when an
529 ancient perl without proper utf8 support is used.
530
531 "utf8_check($data)"
532 Check if we're using a perl with proper utf8 support, by verifying
533 the Encode.pm module is available for loading.
534
535 "home_dir()"
536 Return the path to the home directory of the current user.
537
539 Mike Schilli, <m@perlmeister.com>
540
542 Copyright (C) 2004-2007 by Mike Schilli
543
544 This library is free software; you can redistribute it and/or modify it
545 under the same terms as Perl itself, either Perl version 5.8.3 or, at
546 your option, any later version of Perl 5 you may have available.
547
548
549
550perl v5.34.0 2021-07-22 Sysadm::Install(3)