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