2017-05-14 1 views
2

ssh 터널을 생성하고 원격 호스트의 데이터베이스를 쿼리하기 위해 Perl DBI 연결을 설정하는 perl 스크립트가 있습니다."mux_client_request_session : master에서 읽음 실패 : 파이프가 깨짐"ssh 오류

1 my $ssh = Net::OpenSSH->new('[email protected]'); 
2 $pid = $ssh->spawn({ssh_opts => '-L 127.0.0.1:12345:127.0.0.1:3306'}, 'sleep 3'); 

3 return DBI->connect($dsn, $db_user, $db_pass); 

이 시간의 약 80 ~ 90 %를 작동하지만 나머지 시간은 내가 데이터베이스에 연결하려고이 오류를 얻을 : 실패 마스터에서 읽어 :

mux_client_request_session 깨진 파이프를

이 문제를 해결하는 과정에서 2시 이후에 잠시 잠시 잠을 자면 usleep (10000)으로 100 % 작동합니다. 나는 이것이 왜인지는 모르겠다. 그러나 내가 궁금해하고, 어떻게 문제를 적절하게 해결할 수 있는지 궁금하다.

감사합니다.

답변

3

코드에서 경쟁 조건이 있습니다 : spawn 가끔이 아닌, 때로는 그 명령은 TCP 소켓 시작 DBI connect보다 빠른, 배경에 터널을 시작 ssh 명령을 실행 등 connect이 실패합니다. 데이터베이스로의 연결이 확립 된 후에는 터널을 제거하려면

$ssh->system({ssh_opts => [-O => 'forward', '-L3066:localhost:3066']}) 

:

어쨌든, 나는 보통 터널을 만들 것을 권장 방법은 제어 명령을 사용하는 것입니다

$ssh->system({ssh_opts => [-O => 'cancel', '-L3066:localhost:3066']}); 

또한 DB 연결을 사용하려는 경우 Net::OpenSSH 개체를 활성 상태로 유지해야합니다. 요약

:

sub dbi_connect { 
    my $mysql_port = 3066; 
    my $local_port = 12345; 
    my $dsn = "DBI:mysql:database=$database;host=localhost;port=$local_port"; 
    my $tunnel = join ':', $local_port, 'localhost', $mysql_port; 
    my $ssh = Net::OpenSSH->new($host, ...); 
    $ssh->system({ssh_opts => [-O => 'forward', "-L$tunnel"]}); 
    my $dbi = DBI->connect($dsn, $db_user, $db_pass); 
    $ssh->system({ssh_opts => [-O => 'cancel', "-L$tunnel"]}); 
    return ($dbi, $ssh); 
} 

는 PerlMonks에서 또한 this post 참조하십시오.

+0

감사합니다. $ dsn은 어떻게됩니까? 또한 Windows가 아니기 때문에 4022 대신 mysql 포트로 3306을 사용한다고 가정합니다. – StevieD

+0

'$ dsn'은 터널의 로컬 측을 가리켜 야합니다. 위의 예제를 mysql에 포함시켰다. – salva

+0

감사합니다. 내가 기회를 얻 자마자 나는 이것을 시험 할 것이다. – StevieD

관련 문제