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 Only called when the "content" parameter is used. For the "source"
219 parameter, the upload hooks are used.
220
221 after_change
222 This gets executed right after the file is written. All original
223 parameters, including the applied defaults ("ensure => 'present'",
224 resolved path for "source"), and any returned results are passed to
225 it.
226
227 Only called when the "content" parameter is used. For the "source"
228 parameter, the upload hooks are used.
229
230 after
231 This gets executed right before the "file()" function returns. All
232 original parameters, including the applied defaults ("ensure =>
233 'present'", resolved path for "source"), and any returned results
234 are passed to it.
235
236 file_write($file_name)
237 This function opens a file for writing (it will truncate the file if it
238 already exists). It returns a Rex::FS::File object on success.
239
240 On failure it will die.
241
242 my $fh;
243 eval {
244 $fh = file_write("/etc/groups");
245 };
246
247 # catch an error
248 if($@) {
249 print "An error occurred. $@.\n";
250 }
251
252 # work with the filehandle
253 $fh->write("...");
254 $fh->close;
255
256 file_append($file_name)
257 file_read($file_name)
258 This function opens a file for reading. It returns a Rex::FS::File
259 object on success.
260
261 On failure it will die.
262
263 my $fh;
264 eval {
265 $fh = read("/etc/groups");
266 };
267
268 # catch an error
269 if($@) {
270 print "An error occurred. $@.\n";
271 }
272
273 # work with the filehandle
274 my $content = $fh->read_all;
275 $fh->close;
276
277 cat($file_name)
278 This function returns the complete content of $file_name as a string.
279
280 print cat "/etc/passwd";
281
282 delete_lines_matching($file, $regexp)
283 Delete lines that match $regexp in $file.
284
285 task "clean-logs", sub {
286 delete_lines_matching "/var/log/auth.log" => "root";
287 };
288
289 delete_lines_according_to($search, $file, @options)
290 This is the successor of the delete_lines_matching() function. This
291 function also allows the usage of on_change and on_no_change hooks.
292
293 It will search for $search in $file and remove the found lines. If
294 on_change hook is present it will execute this if the file was changed.
295
296 task "cleanup", "server1", sub {
297 delete_lines_according_to qr{^foo:}, "/etc/passwd",
298 on_change => sub {
299 say "removed user foo.";
300 };
301 };
302
303 append_if_no_such_line($file, $new_line, @regexp)
304 Append $new_line to $file if none in @regexp is found. If no regexp is
305 supplied, the line is appended unless there is already an identical
306 line in $file.
307
308 task "add-group", sub {
309 append_if_no_such_line "/etc/groups", "mygroup:*:100:myuser1,myuser2", on_change => sub { service sshd => "restart"; };
310 };
311
312 Since 0.42 you can use named parameters as well
313
314 task "add-group", sub {
315 append_if_no_such_line "/etc/groups",
316 line => "mygroup:*:100:myuser1,myuser2",
317 regexp => qr{^mygroup},
318 on_change => sub {
319 say "file was changed, do something.";
320 };
321
322 append_if_no_such_line "/etc/groups",
323 line => "mygroup:*:100:myuser1,myuser2",
324 regexp => [qr{^mygroup:}, qr{^ourgroup:}]; # this is an OR
325 };
326
327 append_or_amend_line($file, $line, @regexp)
328 Similar to append_if_no_such_line, but if the line in the regexp is
329 found, it will be updated. Otherwise, it will be appended.
330
331 task "update-group", sub {
332 append_or_amend_line "/etc/groups",
333 line => "mygroup:*:100:myuser3,myuser4",
334 regexp => qr{^mygroup},
335 on_change => sub {
336 say "file was changed, do something.";
337 },
338 on_no_change => sub {
339 say "file was not changed, do something.";
340 };
341 };
342
343 extract($file [, %options])
344 This function extracts a file. The target directory optionally
345 specified with the `to` option will be created automatically.
346
347 Supported formats are .box, .tar, .tar.gz, .tgz, .tar.Z, .tar.bz2,
348 .tbz2, .zip, .gz, .bz2, .war, .jar.
349
350 task prepare => sub {
351 extract "/tmp/myfile.tar.gz",
352 owner => "root",
353 group => "root",
354 to => "/etc";
355
356 extract "/tmp/foo.tgz",
357 type => "tgz",
358 mode => "g+rwX";
359 };
360
361 Can use the type=> option if the file suffix has been changed. (types
362 are tar, tgz, tbz, zip, gz, bz2)
363
364 sed($search, $replace, $file)
365 Search some string in a file and replace it.
366
367 task sar => sub {
368 # this will work line by line
369 sed qr{search}, "replace", "/var/log/auth.log";
370
371 # to use it in a multiline way
372 sed qr{search}, "replace", "/var/log/auth.log",
373 multiline => TRUE;
374 };
375
376 Like similar file management commands, it also supports "on_change" and
377 "on_no_change" hooks.
378
379
380
381perl v5.32.1 2021-03-06 Rex::Commands::File(3)