shivams
shivams

Reputation: 2717

Not able to connect to socket using socat

I am trying to parse rsyslog logs. For this i am sending all my logs to socat which is then sending them to Unix Domain Socket. That socket is created via perl script which is listening on that socket to parse logs.

My bash script to which rsyslog is sending all log is

if [ ! `pidof -x log_parser.pl` ] 
  then
./log_parser.pl & 1>&1
fi

if [ -S /tmp/sock ] 
then
/usr/bin/socat -t0 -T0   - UNIX-CONNECT:/tmp/sock 2>> /var/log/socat.log
fi

/tmp/sock is created using perl script log_parser.pl which is

use IO::Socket::UNIX;

sub socket_create {
    $socket_path = '/tmp/sock';
    unlink($socket_path);

    $listner = IO::Socket::UNIX->new(
       Type   => SOCK_STREAM,
       Local  => $socket_path,
       Listen => SOMAXCONN,
       Blocking => 0,
    )
       or die("Can't create server socket: $!\n");

   $socket = $listner->accept()
      or die("Can't accept connection: $!\n");
   }

   socket_create();
   while(1) {

   chomp($line=<$socket>);
   print "$line\n";
   }

There is this error i am getting from socat which is

2015/02/24 11:58:01 socat[4608] E connect(3, AF=1 "/tmp/sock", 11): Connection refused

I am no champion in sockets so i am not able to understand what is this. Please help. Thanks in advance.

The main issue is that when i kill my perl script then bash script is suppose to call it again and start it. What actually happening is that sript is started but socat is not started instead it give this error and never start.

Upvotes: 0

Views: 7122

Answers (1)

7stud
7stud

Reputation: 48589

I can duplicate your error if I don't run your perl program before trying to use socat. Here is what works for me:

1) my_prog.pl:

use strict; 
use warnings; 
use 5.016;
use Data::Dumper;
use IO::Socket::UNIX;

my $socket_path = '/tmp/sock';
unlink $socket_path; 

my $socket = IO::Socket::UNIX->new(
    Local  => $socket_path,
    Type   => SOCK_STREAM,
    Listen => SOMAXCONN,
) or die "Couldn't create socket: $!";

say "Connected to $socket_path...";
my $CONN = $socket->accept()
    or die "Whoops! Failed to open a connection: $!";

{
    local $/ = undef;   #local -> restore previous value when the enclosing scope, delimited by the braces, is exited.
                        #Setting $/ to undef puts file reads in 'slurp mode' => whole file is considered one line.
    my $file = <$CONN>; #Read one line.
    print $file;
}`

2) $ perl my_prog.pl

3) socat -u -v GOPEN:./data.txt UNIX-CONNECT:/tmp/sock

The -u and -v options aren't necessary:

-u            Uses  unidirectional  mode.  The  first address is only used for
              reading, and the second address is only used for writing  (exam-
              ple).


-v            Writes the transferred data not only to  their  target  streams,
              but  also to stderr. The output format is text with some conver-
              sions for readability, and prefixed with "> " or "< " indicating
              flow directions.

4) You can also do it like this:

cat data.txt | socat STDIN UNIX-CONNECT:/tmp/sock

Pipe stdout of cat command to socat, then list STDIN as one of socat's files.

Response to comment:

This bash script works for me:

#!/usr/bin/env bash

echo 'bash script'

../pperl_programs/my_prog.pl &
sleep 1s

socat GOPEN:./data.txt UNIX-CONNECT:/tmp/sock

It looks like the perl script doesn't have enough time to setup the socket before socat tries to transfer data.

Upvotes: 1

Related Questions