1Rex::Commands::File(3)User Contributed Perl DocumentationRex::Commands::File(3)
2
3
4
6 Rex::Commands::File - Transparent File Manipulation
7
9 With this module you can manipulate files.
10
12 task "read_passwd", "server01", sub {
13 my $fh = file_read "/etc/passwd";
14 for my $line ($fh->read_all) {
15 print $line;
16 }
17 $fh->close;
18 };
19
20 task "read_passwd2", "server01", sub {
21 say cat "/etc/passwd";
22 };
23
24
25 task "write_passwd", "server01", sub {
26 my $fh = file_write "/etc/passwd";
27 $fh->write("root:*:0:0:root user:/root:/bin/sh\n");
28 $fh->close;
29 };
30
31 delete_lines_matching "/var/log/auth.log", matching => "root";
32 delete_lines_matching "/var/log/auth.log", matching => qr{Failed};
33 delete_lines_matching "/var/log/auth.log",
34 matching => "root", qr{Failed}, "nobody";
35
36 file "/path/on/the/remote/machine",
37 source => "/path/on/local/machine";
38
39 file "/path/on/the/remote/machine",
40 content => "foo bar";
41
42 file "/path/on/the/remote/machine",
43 source => "/path/on/local/machine",
44 owner => "root",
45 group => "root",
46 mode => 400,
47 on_change => sub { say shift, " was changed."; },
48 on_no_change => sub { say shift, " wasn't changed."; };
49
51 template($file [, %params])
52 Parse a template and return the content.
53
54 By default, it uses Rex::Template. If any of the template_ng or 1.3 (or
55 newer) feature flag is enabled, then Rex::Template::NG is used instead
56 of this module (recommended).
57
58 For more advanced functionality, you may use your favorite template
59 engine via the set_template_function configuration option.
60
61 Template variables may be passed either as hash or a hash reference.
62 The following calls are equivalent:
63
64 template( $template, variable => value );
65
66 template( $template, { variable => value } );
67
68 List of exposed template variables
69
70 The following template variables are passed to the underlying
71 templating engine, in order of precedence from low to high (variables
72 of the same name are overridden by the next level aka "last one wins"):
73
74 task parameters
75 All task parameters coming from the command line via
76 "rex taskname --param=value", or from calling a task as a function,
77 like taskname( { param => value } ).
78
79 resource parameters
80 All resource parameters as returned by
81 "Rex::Resource->get_current_resource()->get_all_parameters", when
82 called inside a resource.
83
84 explicit template variables
85 All manually specified, explicit template variables passed to
86 template().
87
88 system information
89 The results from all available Rex::Hardware modules as returned by
90 "Rex::Hardware->get('All')".
91
92 Pass "__no_sys_info__ => TRUE" as a template variable to disable
93 including system information:
94
95 my $content = template( $template, __no_sys_info__ => TRUE );
96
97 Embedded templates
98
99 Use "__DATA__" to embed templates at the end of the file. Prefix
100 embedded template names with "@". If embedding multiple templates, mark
101 their end with @end.
102
103 Single template
104
105 my $content = template( '@hello', name => 'world' ); # Hello, world!
106 __DATA__
107 @hello
108 Hello, <%= $name -%>!
109
110 Multiple templates
111
112 Use @end to separate multiple templates inside "__DATA__".
113
114 my $content = template( '@hello', name => 'world' ); # Hello, world!
115 my $alternative = template( '@hi', name => 'world' ); # Hi, world!
116
117 __DATA__
118 @hello
119 Hello, <%= $name -%>!
120 @end
121
122 @hi
123 Hi, <%= $name -%>!
124 @end
125
126 File templates
127
128 my $content = template("/files/templates/vhosts.tpl",
129 name => "test.lan",
130 webmaster => 'webmaster@test.lan');
131
132 The file name specified is subject to "path_map" processing as
133 documented under the file() function to resolve to a physical file
134 name.
135
136 In addition to the "path_map" processing, if the -E command line switch
137 is used to specify an environment name, existence of a file ending with
138 '.<env>' is checked and has precedence over the file without one, if it
139 exists. E.g. if rex is started as:
140
141 $ rex -E prod task1
142
143 then in task1 defined as:
144
145 task "task1", sub {
146 say template("files/etc/ntpd.conf");
147 };
148
149 will print the content of 'files/etc/ntpd.conf.prod' if it exists.
150
151 Note: the appended environment mechanism is always applied, after the
152 'path_map' mechanism, if that is configured.
153
154 file($file_name [, %options])
155 This function is the successor of install file. Please use this
156 function to upload files to your server.
157
158 task "prepare", "server1", "server2", sub {
159 file "/file/on/remote/machine",
160 source => "/file/on/local/machine";
161
162 file "/etc/hosts",
163 content => template("templates/etc/hosts.tpl"),
164 owner => "user",
165 group => "group",
166 mode => 700,
167 on_change => sub { say "Something was changed." },
168 on_no_change => sub { say "Nothing has changed." };
169
170 file "/etc/motd",
171 content => `fortune`;
172
173 file "/etc/named.conf",
174 content => template("templates/etc/named.conf.tpl"),
175 no_overwrite => TRUE; # this file will not be overwritten if already exists.
176
177 file "/etc/httpd/conf/httpd.conf",
178 source => "/files/etc/httpd/conf/httpd.conf",
179 on_change => sub { service httpd => "restart"; };
180
181 file "/etc/named.d",
182 ensure => "directory", # this will create a directory
183 owner => "root",
184 group => "root";
185
186 file "/etc/motd",
187 ensure => "absent"; # this will remove the file or directory
188
189 };
190
191 The first parameter is either a string or an array reference. In the
192 latter case the function is called for all strings in the array.
193 Therefore, the following constructs are equivalent:
194
195 file '/tmp/test1', ensure => 'directory';
196 file '/tmp/test2', ensure => 'directory';
197
198 file [ qw( /tmp/test1 /tmp/test2 ) ], ensure => 'directory'; # use array ref
199
200 file [ glob('/tmp/test{1,2}') ], ensure => 'directory'; # explicit glob call for array contents
201
202 Use the glob carefully as it can leak local filesystem information
203 (e.g. when using wildcards).
204
205 The source is subject to a path resolution algorithm. This algorithm
206 can be configured using the set function to set the value of the
207 path_map variable to a hash containing path prefixes as its keys. The
208 associated values are arrays listing the prefix replacements in order
209 of (decreasing) priority.
210
211 set "path_map", {
212 "files/" => [ "files/{environment}/{hostname}/_root_/",
213 "files/{environment}/_root_/" ]
214 };
215
216 With this configuration, the file "files/etc/ntpd.conf" will be probed
217 for in the following locations:
218
219 - files/{environment}/{hostname}/_root_/etc/ntpd.conf
220 - files/{environment}/_root_/etc/ntpd.conf
221 - files/etc/ntpd.conf
222
223 Furthermore, if a path prefix matches multiple prefix entries in
224 'path_map', e.g. "files/etc/ntpd.conf" matching both "files/" and
225 "files/etc/", the longer matching prefix(es) have precedence over
226 shorter ones. Note that keys without a trailing slash (i.e.
227 "files/etc") will be treated as having a trailing slash when matching
228 the prefix ("files/etc/").
229
230 If no file is found using the above procedure and source is relative,
231 it will search from the location of your Rexfile or the .pm file if you
232 use Perl packages.
233
234 All the possible variables ('{environment}', '{hostname}', ...) are
235 documented in the CMDB YAML documentation.
236
237 Hooks
238
239 This function supports the following hooks:
240
241 before
242 This gets executed before anything is done. All original parameters
243 are passed to it, including the applied defaults ("ensure =>
244 'present'", resolved path for "source").
245
246 The return value of this hook overwrites the original parameters of
247 the function call.
248
249 before_change
250 This gets executed right before the new file is written. All
251 original parameters are passed to it, including the applied
252 defaults ("ensure => 'present'", resolved path for "source").
253
254 after_change
255 This gets executed right after the file is written. All original
256 parameters, including the applied defaults ("ensure => 'present'",
257 resolved path for "source"), and any returned results are passed to
258 it.
259
260 after
261 This gets executed right before the file() function returns. All
262 original parameters, including the applied defaults ("ensure =>
263 'present'", resolved path for "source"), and any returned results
264 are passed to it.
265
266 file_write($file_name)
267 This function opens a file for writing (it will truncate the file if it
268 already exists). It returns a Rex::FS::File object on success.
269
270 On failure it will die.
271
272 my $fh;
273 eval {
274 $fh = file_write("/etc/groups");
275 };
276
277 # catch an error
278 if($@) {
279 print "An error occurred. $@.\n";
280 }
281
282 # work with the filehandle
283 $fh->write("...");
284 $fh->close;
285
286 file_append($file_name)
287 file_read($file_name)
288 This function opens a file for reading. It returns a Rex::FS::File
289 object on success.
290
291 On failure it will die.
292
293 my $fh;
294 eval {
295 $fh = file_read("/etc/groups");
296 };
297
298 # catch an error
299 if($@) {
300 print "An error occurred. $@.\n";
301 }
302
303 # work with the filehandle
304 my $content = $fh->read_all;
305 $fh->close;
306
307 cat($file_name)
308 This function returns the complete content of $file_name as a string.
309
310 print cat "/etc/passwd";
311
312 delete_lines_matching($file, $regexp)
313 Delete lines that match $regexp in $file.
314
315 task "clean-logs", sub {
316 delete_lines_matching "/var/log/auth.log" => "root";
317 };
318
319 delete_lines_according_to($search, $file [, @options])
320 This is the successor of the delete_lines_matching() function. This
321 function also allows the usage of on_change and on_no_change hooks.
322
323 It will search for $search in $file and remove the found lines. If
324 on_change hook is present it will execute this if the file was changed.
325
326 task "cleanup", "server1", sub {
327 delete_lines_according_to qr{^foo:}, "/etc/passwd",
328 on_change => sub {
329 say "removed user foo.";
330 };
331 };
332
333 append_if_no_such_line($file, $new_line [, @regexp])
334 Append $new_line to $file if none in @regexp is found. If no regexp is
335 supplied, the line is appended unless there is already an identical
336 line in $file.
337
338 task "add-group", sub {
339 append_if_no_such_line "/etc/groups", "mygroup:*:100:myuser1,myuser2", on_change => sub { service sshd => "restart"; };
340 };
341
342 Since 0.42 you can use named parameters as well
343
344 task "add-group", sub {
345 append_if_no_such_line "/etc/groups",
346 line => "mygroup:*:100:myuser1,myuser2",
347 regexp => qr{^mygroup},
348 on_change => sub {
349 say "file was changed, do something.";
350 };
351
352 append_if_no_such_line "/etc/groups",
353 line => "mygroup:*:100:myuser1,myuser2",
354 regexp => [qr{^mygroup:}, qr{^ourgroup:}]; # this is an OR
355 };
356
357 append_or_amend_line($file, $line [, @regexp])
358 Similar to append_if_no_such_line, but if the line in the regexp is
359 found, it will be updated. Otherwise, it will be appended.
360
361 task "update-group", sub {
362 append_or_amend_line "/etc/groups",
363 line => "mygroup:*:100:myuser3,myuser4",
364 regexp => qr{^mygroup},
365 on_change => sub {
366 say "file was changed, do something.";
367 },
368 on_no_change => sub {
369 say "file was not changed, do something.";
370 };
371 };
372
373 extract($file [, %options])
374 This function extracts a file. The target directory optionally
375 specified with the `to` option will be created automatically.
376
377 Supported formats are .box, .tar, .tar.gz, .tgz, .tar.Z, .tar.bz2,
378 .tbz2, .zip, .gz, .bz2, .war, .jar.
379
380 task prepare => sub {
381 extract "/tmp/myfile.tar.gz",
382 owner => "root",
383 group => "root",
384 to => "/etc";
385
386 extract "/tmp/foo.tgz",
387 type => "tgz",
388 mode => "g+rwX";
389 };
390
391 Can use the type=> option if the file suffix has been changed. (types
392 are tar, tgz, tbz, zip, gz, bz2)
393
394 sed($search, $replace, $file [, %options])
395 Search some string in a file and replace it.
396
397 task sar => sub {
398 # this will work line by line
399 sed qr{search}, "replace", "/var/log/auth.log";
400
401 # to use it in a multiline way
402 sed qr{search}, "replace", "/var/log/auth.log",
403 multiline => TRUE;
404 };
405
406 Like similar file management commands, it also supports "on_change" and
407 "on_no_change" hooks.
408
409
410
411perl v5.36.1 2023-08-07 Rex::Commands::File(3)