私は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' &