Merge branch 'collectd-4.3' into collectd-4.4
[collectd.git] / contrib / cussh.pl
1 #!/usr/bin/perl
2 #
3 # collectd - contrib/cussh.pl
4 # Copyright (C) 2007-2008  Sebastian Harl
5 #
6 # This program is free software; you can redistribute it and/or modify it
7 # under the terms of the GNU General Public License as published by the
8 # Free Software Foundation; only version 2 of the License is applicable.
9 #
10 # This program is distributed in the hope that it will be useful, but
11 # WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 # General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License along
16 # with this program; if not, write to the Free Software Foundation, Inc.,
17 # 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
18 #
19 # Author:
20 #   Sebastian Harl <sh at tokkee.org>
21 #
22
23 =head1 NAME
24
25 cussh - collectd UNIX socket shell
26
27 =head1 SYNOPSIS
28
29 B<cussh> [I<E<lt>pathE<gt>>]
30
31 =head1 DESCRIPTION
32
33 B<collectd>'s unixsock plugin allows external programs to access the values it
34 has collected or received and to submit own values. This is a little
35 interactive frontend for this plugin.
36
37 =head1 OPTIONS
38
39 =over 4
40
41 =item I<E<lt>pathE<gt>>
42
43 The path to the UNIX socket provided by collectd's unixsock plugin. (Default:
44 F</var/run/collectd-unixsock>)
45
46 =back
47
48 =cut
49
50 use strict;
51 use warnings;
52
53 use Collectd::Unixsock();
54
55 { # main
56         my $path = $ARGV[0] || "/var/run/collectd-unixsock";
57         my $sock = Collectd::Unixsock->new($path);
58
59         my $cmds = {
60                 HELP    => \&cmd_help,
61                 PUTVAL  => \&putval,
62                 GETVAL  => \&getval,
63                 FLUSH   => \&flush,
64                 LISTVAL => \&listval,
65         };
66
67         if (! $sock) {
68                 print STDERR "Unable to connect to $path!\n";
69                 exit 1;
70         }
71
72         print "cussh version 0.2, Copyright (C) 2007-2008 Sebastian Harl\n"
73                 . "cussh comes with ABSOLUTELY NO WARRANTY. This is free software,\n"
74                 . "and you are welcome to redistribute it under certain conditions.\n"
75                 . "See the GNU General Public License 2 for more details.\n\n";
76
77         while (1) {
78                 print "cussh> ";
79                 my $line = <STDIN>;
80
81                 last if (! $line);
82
83                 chomp $line;
84
85                 last if ($line =~ m/^quit$/i);
86
87                 my ($cmd) = $line =~ m/^(\w+)\s*/;
88                 $line = $';
89
90                 next if (! $cmd);
91                 $cmd = uc $cmd;
92
93                 my $f = undef;
94                 if (defined $cmds->{$cmd}) {
95                         $f = $cmds->{$cmd};
96                 }
97                 else {
98                         print STDERR "ERROR: Unknown command $cmd!\n";
99                         next;
100                 }
101
102                 if (! $f->($sock, $line)) {
103                         print STDERR "ERROR: Command failed!\n";
104                         next;
105                 }
106         }
107
108         $sock->destroy();
109         exit 0;
110 }
111
112 sub getid {
113         my $string = shift || return;
114
115         print $$string . $/;
116         my ($h, $p, $pi, $t, $ti) =
117                 $$string =~ m#^([^/]+)/([^/-]+)(?:-([^/]+))?/([^/-]+)(?:-([^/]+))?\s*#;
118         $$string = $';
119
120         return if ((! $h) || (! $p) || (! $t));
121
122         my %id = ();
123
124         ($id{'host'}, $id{'plugin'}, $id{'type'}) = ($h, $p, $t);
125
126         $id{'plugin_instance'} = $pi if defined ($pi);
127         $id{'type_instance'} = $ti if defined ($ti);
128         return \%id;
129 }
130
131 sub putid {
132         my $ident = shift || return;
133
134         my $string;
135
136         $string = $ident->{'host'} . "/" . $ident->{'plugin'};
137
138         if (defined $ident->{'plugin_instance'}) {
139                 $string .= "-" . $ident->{'plugin_instance'};
140         }
141
142         $string .= "/" . $ident->{'type'};
143
144         if (defined $ident->{'type_instance'}) {
145                 $string .= "-" . $ident->{'type_instance'};
146         }
147         return $string;
148 }
149
150 =head1 COMMANDS
151
152 =over 4
153
154 =item B<HELP>
155
156 =cut
157
158 sub cmd_help {
159         print <<HELP;
160 Available commands:
161   HELP
162   PUTVAL
163   GETVAL
164   FLUSH
165   LISTVAL
166
167 See the embedded Perldoc documentation for details. To do that, run:
168   perldoc $0
169 HELP
170         return 1;
171 } # cmd_help
172
173 =item B<GETVAL> I<Identifier>
174
175 =cut
176
177 sub putval {
178         my $sock = shift || return;
179         my $line = shift || return;
180
181         my $id = getid(\$line);
182
183         if (! $id) {
184                 print STDERR $sock->{'error'} . $/;
185                 return;
186         }
187
188         my ($time, @values) = split m/:/, $line;
189         return $sock->putval(%$id, time => $time, values => \@values);
190 }
191
192 =item B<PUTVAL> I<Identifier> I<Valuelist>
193
194 =cut
195
196 sub getval {
197         my $sock = shift || return;
198         my $line = shift || return;
199
200         my $id = getid(\$line);
201
202         if (! $id) {
203                 print STDERR $sock->{'error'} . $/;
204                 return;
205         }
206
207         my $vals = $sock->getval(%$id);
208
209         if (! $vals) {
210                 print STDERR $sock->{'error'} . $/;
211                 return;
212         }
213
214         foreach my $key (keys %$vals) {
215                 print "\t$key: $vals->{$key}\n";
216         }
217         return 1;
218 }
219
220 =item B<FLUSH> [B<timeout>=I<$timeout>] [B<plugin>=I<$plugin>[ ...]]
221
222 =cut
223
224 sub flush {
225         my $sock = shift || return;
226         my $line = shift;
227
228         my $res;
229
230         if (! $line) {
231                 $res = $sock->flush();
232         }
233         else {
234                 my %args = ();
235
236                 foreach my $i (split m/ /, $line) {
237                         my ($option, $value) = $i =~ m/^([^=]+)=(.+)$/;
238                         next if (! ($option && $value));
239
240                         if ($option eq "plugin") {
241                                 push @{$args{"plugins"}}, $value;
242                         }
243                         elsif ($option eq "timeout") {
244                                 $args{"timeout"} = $value;
245                         }
246                         else {
247                                 print STDERR "Invalid option \"$option\".\n";
248                                 return;
249                         }
250                 }
251
252                 $res = $sock->flush(%args);
253         }
254
255         if (! $res) {
256                 print STDERR $sock->{'error'} . $/;
257                 return;
258         }
259         return 1;
260 }
261
262 =item B<LISTVAL>
263
264 =cut
265
266 sub listval {
267         my $sock = shift || return;
268
269         my @res;
270
271         @res = $sock->listval();
272
273         if (! @res) {
274                 print STDERR $sock->{'error'} . $/;
275                 return;
276         }
277
278         foreach my $ident (@res) {
279                 print $ident->{'time'} . " " . putid($ident) . $/;
280         }
281         return 1;
282 }
283
284 =back
285
286 These commands follow the exact same syntax as described in
287 L<collectd-unixsock(5)>.
288
289 =head1 SEE ALSO
290
291 L<collectd(1)>, L<collectd-unisock(5)>
292
293 =head1 AUTHOR
294
295 Written by Sebastian Harl E<lt>sh@tokkee.orgE<gt>.
296
297 B<collectd> has been written by Florian Forster and others.
298
299 =head1 COPYRIGHT
300
301 Copyright (C) 2007 Sebastian Harl.
302
303 This program is free software; you can redistribute it and/or modify it under
304 the terms of the GNU General Public License as published by the Free Software
305 Foundation; only version 2 of the License is applicable.
306
307 =cut
308
309 # vim: set sw=4 ts=4 tw=78 noexpandtab :