$ crontab -l # Edit this file to introduce tasks to be run by cron. ... # m h dom mon dow command */17 * * * * hostname | socat -s - UDP-DATAGRAM:255.255.255.255:12340,broadcast 2>/dev/null $ #### #!/usr/bin/env perl use warnings; use strict; use 5.010; no feature 'switch'; =head1 SYNOPSIS Waits for message(s) on a UDP port and when a message is received, prints the IP address from which each message was received. udplisten.pl [-m] [-c COUNT] [-a] [-p PORT] [-e EXPR] [-b RXSZ] OPTIONS: -m - Output the entire message, not just the IP address -c COUNT - Exit after receiving this many messages (default=1) -a - Continuously output all messages (overrides -c) -p PORT - UDP port number (default=12340) -e EXPR - Output only messages which match this Perl expression -b RXSZ - Receive length (default=1024) =head1 DETAILS The message can be transmitted, for example, via the following L entry (note: C): * * * * * echo "HELLO xyZ129" | socat - UDP-DATAGRAM:255.255.255.255:12340,broadcast The string used can be completely random; the idea is for it to be unique to your device so you can identify it, for example: udplisten.pl -e '/HELLO xyZ129/' Two alternate ways to listen are via L or L (note these will receive and print I messages on that port): netcat -ul 12340 # may need to use -p12340 instead socat -u udp-recv:12340 - Don't forget to open the port for incoming UDP traffic on your local firewall, for example for L: ufw allow in 12340/udp B that the choice of port number above is completely random. At the time of writing, this port appears to be unused (L), but if you've got other things on your network that use this port, choose a different one. You're also free to, for example, use different ports for different devices. =head1 AUTHOR, COPYRIGHT, AND LICENSE Copyright (c) 2016 Hauke Daempfling (haukex@zero-g.net) at the Leibniz Institute of Freshwater Ecology and Inland Fisheries (IGB), Berlin, Germany, L This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see L. =cut use Getopt::Std 'getopts'; use Pod::Usage 'pod2usage'; use IO::Socket::INET (); use Data::Dumper; use DateTime; use DateTime::Format::Duration; sub HELP_MESSAGE { pod2usage( -output => shift ); return } sub VERSION_MESSAGE { say {shift} q$udplisten.pl v2.00$; return } $Getopt::Std::STANDARD_HELP_VERSION = 1; getopts( 'mc:ap:e:b:', \my %opts ) or pod2usage; my $FULLMSG = !!$opts{m}; my $COUNT = $opts{c} // 1; pod2usage("Bad count") unless $COUNT && $COUNT =~ /^\d+$/ && $COUNT > 0; my $ALLMSGS = !!$opts{a}; my $PORT = $opts{p} // 12340; pod2usage("Bad port") unless $PORT && $PORT =~ /^\d+$/ && $PORT > 0; my $EXPR = $opts{e}; my $RXSZ = $opts{b} // 1024; pod2usage("Bad receive length") unless $RXSZ && $RXSZ =~ /^\d+$/ && $RXSZ > 0; pod2usage("Extra arguments") if @ARGV; my $sock = IO::Socket::INET->new( LocalPort => $PORT, Proto => 'udp', ) or die "error in socket creation: $!"; my $count = 0; my $dt; my $start = DateTime->now; say "Start time is: ", $start->hms; my $later; RXLOOP: while (1) { defined $sock->recv( my $rx, $RXSZ ) or die "error during recv: $!"; my $peeraddr = $sock->peerhost; my $match = 1; if ( defined $EXPR ) { local $_ = $rx; eval "\$match = do { package CodeEval; $EXPR }; 1" or die "Perl expression failed: " . ( $@ || "Unknown error" ); } next RXLOOP unless $match; say "rx is $rx"; say $FULLMSG ? "From $peeraddr: " . dumpstr($rx) : "$peeraddr"; $dt = DateTime->now; say "Time is: ", $dt->hms; $later = $dt; last RXLOOP if !$ALLMSGS && ++$count >= $COUNT; } $sock->close; my $d = DateTime::Format::Duration->new( pattern => '%Y years, %m months, %e days, ' . '%H hours, %M minutes, %S seconds' ); my $duration_object = $later - $start; say $d->format_duration($duration_object); sub dumpstr { chomp( my $s = Data::Dumper->new( [ '' . shift ] )->Terse(1)->Useqq(1)->Dump ); return $s; } #### $ ./2.udplisten.pl -m -c 2 Start time is: 23:30:43 rx is mypi From 192.168.red.acted: "mypi\n" Time is: 23:34:01 rx is mypi From 192.168.red.acted: "mypi\n" Time is: 23:51:01 0 years, 00 months, 0 days, 00 hours, 20 minutes, 18 seconds $ #### # patch 4/20/2022 -*.*;auth,authpriv.none -/var/log/syslog +*.*;cron,auth,authpriv.none -/var/log/syslog #### Apr 20 16:41:59 mypi systemd[1]: Stopped System Logging Service. Apr 20 16:41:59 mypi systemd[1]: Starting System Logging Service... Apr 20 16:41:59 mypi rsyslogd: error during parsing file /etc/rsyslog.conf, on or before line 94: errors occured in file '/etc/rsyslog.conf' around line 94 [v8.1901.0 try https://www.rsyslog.com/e/2207 ] Apr 20 16:41:59 mypi rsyslogd: error during parsing file /etc/rsyslog.conf, on or before line 95: invalid character '+' - is there an invalid escape sequence somewhere? [v8.1901.0 try https://www.rsyslog.com/e/2207 ] Apr 20 16:41:59 mypi systemd[1]: Started System Logging Service. #### ############### #### RULES #### ############### # # First some standard log files. Log by facility. # auth,authpriv.* /var/log/auth.log #*.*;auth,authpriv.none -/var/log/syslog *.*;cron,auth,authpriv.none -/var/log/syslog #cron.* /var/log/cron.log daemon.* -/var/log/daemon.log kern.* -/var/log/kern.log lpr.* -/var/log/lpr.log mail.* -/var/log/mail.log user.* -/var/log/user.log