2

我想解析.ssh/config文件中包含的代理信息,并将每个具有相关代理信息的主机与代理信息一起显示。应该过滤掉没有任何代理信息的主机。手册页.ssh/confighttp ://man-wiki.net/index.php/5:ssh_config

这应该通过 Bash 下的 Unix shell 脚本完成,因此首选 Perl、awk 或 sed 等标准工具。

示例输入文件:

Host ssh.foo.com
    User ssh
    HostName ssh.foo.com
    Port 443
    ProxyCommand /usr/local/bin/corkscrew proxy 8080 %h %p ~/.ssh/proxyauth

Host ci
    HostName 127.0.0.2
    User ci

Host nightly
    HostName 192.168.1.1
    User goodnight

Host foobar.org
    User git
    HostName foobar.org
    Port 443
    ProxyCommand /usr/local/bin/corkscrew proxy 8080 %h %p ~/.ssh/proxyauth

Host integration
    HostName 192.168.1.2
    User int

预期的输出应如下所示:

Host: ssh.foo.com - Proxy: /usr/local/bin/corkscrew proxy 8080 %h %p ~/.ssh/proxyauth
Host: foobar.org - Proxy: /usr/local/bin/corkscrew proxy 8080 %h %p ~/.ssh/proxyauth

这里的困难是搜索必须覆盖多行。

4

6 回答 6

6

尝试以下awk命令:

awk '
    $1 == "Host" { 
        host = $1 ": " $2; 
        next; 
    } 
    $1 == "ProxyCommand" { 
        $1 = ""; 
        sub( /^[[:space:]]*/, "" ); 
        printf "%s - Proxy: %s\n", host, $0;
    }
' .ssh/config

它产生:

Host: ssh.foo.com - Proxy: /usr/local/bin/corkscrew proxy 8080 %h %p ~/.ssh/proxyauth
Host: foobar.org - Proxy: /usr/local/bin/corkscrew proxy 8080 %h %p ~/.ssh/proxyauth
于 2012-10-08T09:54:46.123 回答
2

awk oneliner 可能会满足您的要求:

awk -v RS="" '/Proxy/{gsub(/\n/,"");gsub(/\s*User.*ProxyCommand/,"- Proxy:");print}'file

测试(a.txt 是您的输入文件)

kent$  awk -v RS="" '/Proxy/{gsub(/\n/,"");gsub(/\s*User.*ProxyCommand/,"- Proxy:");print}' a.txt                                                                  
Host ssh.foo.com    - Proxy: /usr/local/bin/corkscrew proxy 8080 %h %p ~/.ssh/proxyauth
Host foobar.org    - Proxy: /usr/local/bin/corkscrew proxy 8080 %h %p ~/.ssh/proxyauth
于 2012-10-08T09:52:16.317 回答
2

只是为了好玩,这是一个讨厌的 sed 命令,似乎可以完成此操作。

sed -n '/^[Hh]ost/{:r;h;:l;n;/^[Hh]ost/!{/[Pp]roxy/H;bl};/^[Hh]ost/{x;/[Pp]roxy/{s/\n\s*/ - /;s/[Cc]ommand/:/;s/[Hh]ost/\0:/;p};x;br}}' ~/.ssh/config

无论如何,这更多是出于演示目的,因为其他解决方案更容易掌握。对此的评论意见:

/^[Hh]ost/ {                # Begin on a Host line
    :restart                # Label to jump back to
    h                       # Copy the pattern space to the save space
    :loop                   # Label to jump to when we don't want to wipe out the save space
    n                       # Read in the next line
    /^[Hh]ost/!{            # For lines that aren't host definitions
        /[Pp]roxy/H         # If they are proxy configurations, append the line to the save space
        b loop              # Go to :loop
    }
    /^[Hh]ost/{             # If they are *not* host definitions
        x                   # Exchange the pattern and save spaces
        /[Pp]roxy/{         # If the new pattern space contains a proxy configuration
            s/\n\s*/ - /    # Insert the required separator
            s/[Cc]ommand/:/ # Change "ProxyCommand" to "Proxy:"
            s/[Hh]ost/\0:/  # Change "Host" to "Host:"
            p               # Print the pattern space
        }
        x                   # Exchange the pattern and save spaces
        b restart           # Go to :restart
    }
}

示例输出:

Host: ssh.foo.com - Proxy: /usr/local/bin/corkscrew proxy 8080 %h %p ~/.ssh/proxyauth
Host: foobar.org - Proxy: /usr/local/bin/corkscrew proxy 8080 %h %p ~/.ssh/proxyauth
于 2012-10-08T10:59:42.600 回答
1

一种使用方式GNU sed

sed -nre '/^Host/h;/ProxyCommand/{H;x;s/(Host)(.*)\n +[^ ]+ /\1:\2 - Proxy: /p}' file.txt

结果:

Host: ssh.foo.com - Proxy: /usr/local/bin/corkscrew proxy 8080 %h %p ~/.ssh/proxyauth
Host: foobar.org - Proxy: /usr/local/bin/corkscrew proxy 8080 %h %p ~/.ssh/proxyauth
于 2012-10-08T12:27:41.413 回答
1

你检查过Net::SSH::Perl::Config模块吗?它声称以标准ssh格式读取配置 - 尽管使用了一部分关键字。

配置文件的格式应与 ssh 命令行程序使用的格式相同;有关此格式的信息,请参见 ssh 手册页。Net::SSH::Perl::Config 理解可以存在于这些文件中的配置指令的子集;这个子集与 Net::SSH::Perl 可以支持的功能相匹配。未知的关键字将被简单地跳过。

于 2012-10-08T09:49:19.473 回答
0

尝试这个:

#! /usr/bin/perl
use strict;
use warnings;
open FD, "DATA" || die $!;
my $line = do {local $/; <FD>};
my @a = split /Host\b/, $line;
foreach (@a) {
    if (defined $_ and /^\s*(\S+).*ProxyCommand\s+([^\n]+)/s) {
        print "$1 - Proxy: $2\n";
    }   
}
于 2012-10-09T02:25:50.340 回答