nohup(Ubuntu/Debian 64비트)를 사용하여 콘솔에서 분리할 때 netcat이 예상대로 작동하지 않습니다.

nohup(Ubuntu/Debian 64비트)를 사용하여 콘솔에서 분리할 때 netcat이 예상대로 작동하지 않습니다.

나는 netcat을 계속 실행하고 ssh 세션을 닫으려고 했습니다(또는 ssh 데몬을 중지하기도 했습니다). 그러나 모든 데이터가 기록되기 전에 종료됩니다. SSH가 아닌(로컬) 콘솔에서 테스트하고 있습니다.

nohup nc -l -p 4000  | dd of=/home/myname/test.txt 2>/run/user/myname/stderr  1>/run/user/myname/stdout &

테스트하기 위해 콘솔을 닫고 다른 콘솔에 파일을 덤프합니다.

dd if=/var/log/Xorg.0.log  |  nc localhost 4000

/home/myname/test.txt에는 아무 것도 기록되지 않습니다. 하지만 nohup 명령을 제거하면 test.txt에 덤프된 모든 데이터가 포함됩니다. netcat을 작동시키고 콘솔에서 분리하려면 어떻게 해야 합니까?

답변1

글쎄, 나는 그것을 파헤쳤다 :북면표준 입력을 사용하여 프로그램 실행리디렉션/dev/null에서. 따라서 dd 명령은 nc에서 아무 것도 가져오지 않으며 nc는 쓰기에 실패하고 첫 번째 쓰기 시도에서 자체적으로 닫힐 수 있습니다. 따라서 먼저 다음을 통해 I/O를 라우팅하는 명명된 파이프를 만들어야 합니다.

mkfifo my.pipe

그런 다음 파이프의 입력 파일을 사용하여 dd를 실행합니다.

nohup dd if=./my.pipe of=./test.txt 2>/run/user/myname/stderr  1>/run/user/myname/stdout &

이제 네트워크에서 파이프라인 데이터를 공급할 수 있습니다. 불행하게도 netcat은 nohup에서는 사용할 수 없는 표준 출력에 쓰기 때문에 이 작업을 수행하지 않습니다. netcat의 소스를 수정해야 합니다. (C 컴파일러 없이) 더 쉽게 만들기 위해 "가난한 사람의 Netcat"이라고도 알려진 perl 느슨한 포트를 netcat에 채택할 예정입니다. 음..다시 작성하고 -f 매개변수를 사용하여 파일을 추가했습니다. 오 기능. 그래서 이것이 소스입니다:

#! /usr/bin/perl
# Poor man's Netcat, the famous "TCP/IP swiss army knife"
# Only the basic functions are replicated : 
# - TCP only
# - only : "hostname port" or "-l" with "-p port" 
# but with *extended* functionality for direct file I/O by "-f file"

use strict;
use warnings;

use IO::Socket;
use Getopt::Long;

my $help='';
my $verbose;

my $local_port;
my $listen='';
$main::file_io='';

$SIG{CHLD} = 'IGNORE';

my $result = GetOptions(
        "help|h" => \$help,
        "verbose|v" => \$verbose,
    "local-port|p=i" => \$local_port,
    "listen|l" => \$listen,
        "file-io|f=s" => \$main::file_io,
       );
if ($help eq '' && $listen eq '' && (scalar @ARGV < 2) ) {$help = 1;}
if ($help) {
        print STDERR "Perl loose port of netcat(1)\n";
        print STDERR "usage : $0 [-p local_port] hostname port [-f file-for-input] (client)\n";
        print STDERR "   or : $0 -l -p local_port [-f file-for-output] (server)\n";
        exit(1);
}

# No need to close the socks as they are closed 
# when going out-of-scope
if ($listen) 
  { if (! $local_port) { die "You must specify the port to listen to in server mode\n";}
    # server mode
    my $l_sock = IO::Socket::INET->new(
        Proto => "tcp",
        LocalPort => $local_port,
        Listen => 1,
        Reuse => 1,
    ) or die "Could not create socket: $!";

    my $a_sock = $l_sock->accept(); 
    $l_sock->shutdown(SHUT_RDWR);
    read_from_network($a_sock); #server mode - calling read_data 
  } else 
     { #client mode
    if (scalar @ARGV < 2) { die "You must specify where to connect in client mode\n";}
    my ($remote_host, $remote_port) = @ARGV;
    my $c_sock = IO::Socket::INET->new(
        Proto => "tcp",
        LocalPort => $local_port,
        PeerAddr => $remote_host,
        PeerPort => $remote_port,
    ) or die "Could not create socket, reason: $!";
    write_to_network($c_sock);
    }

sub read_from_network 
 {
    my ($socket) = @_;  my $output_fh;
        if($main::file_io ne '') 
       {
             open($output_fh, ">", $main::file_io) or die "Can't open $main::file_io : $!";
           } else { $output_fh = *STDOUT;}
    close(STDIN);
    copy_data_mono($socket, $output_fh);# *STDOUT
        $socket->shutdown(SHUT_RD); 
        close($output_fh); close(STDOUT);
 }


sub write_to_network 
 {
    my ($socket) = @_;
        my $input_fh;
        if($main::file_io ne '') 
       {
             open($input_fh, "<", $main::file_io) or die "Can't open $main::file_io : $!";
           } else { $input_fh = *STDIN;}
    close(STDOUT);
    copy_data_mono($input_fh,$socket);
        $socket->shutdown(SHUT_WR); 
        close($input_fh);close(STDIN);
 }

sub copy_data_mono {
    my ($src, $dst) = @_;
    my $buf;
        print STDERR "copy_data_mono: output: $dst \n";
    while (my $read_len = sysread($src, $buf, 4096)) 
        {
        my $write_len = $read_len;
        while ($write_len) 
                {
         my $written_len = syswrite($dst, $buf);
         return unless $written_len; # $dst is closed
         $write_len -= $written_len;
        }
    }
}

물론 이제 dd 및 명명된 파이프를 건너뛸 수 있지만 물리 분할에 쓸 때 이 코드가 올바르게 작동하는지 확인하지 않았습니다... 이제 모든 명령은 다음과 같습니다(코드가 netcat_g.pl에 저장되었다고 가정).

mkfifo my.pipe #create a fifo, @ writable FS
nohup dd if=./my.pipe of=./test.txt & 
nohup ./netcat_g.pl -l -p 4000 -f ./my.pipe  &

콘솔을 닫을 수도 있습니다. 가장 큰 단점은 파일 I/O를 지원하고 새 명명된 파이프를 생성하지 않는 한 다른 명령을 연결할 수 없다는 것입니다.

답변2

자체 쉘 인스턴스에서 명령을 실행해야 합니다.

nohup sh -c 'nc -l -p 4000  | dd of=/home/myname/test.txt 2>/run/user/myname/stderr  1>/run/user/myname/stdout' &

답변3

netcat에 추가 "-d" 옵션을 추가해 보십시오(그래서 표준 입력에서 읽으려고 시도하지 않습니다). 콘솔을 닫고 1MB의 데이터를 복사한 후에도 이를 사용하고 별도의 셸을 확장하는 솔루션은 여전히 ​​효과적이었습니다.

nohup sh -c 'nc -d -l 4000 | dd of=/home/user/dir/test.txt 
    2>/home/user/dir/stderr  
    1>/home/user/dir/stdout' &

관련 정보