#!/usr/bin/perl # # $Id$ # # kill_known_host: Remove an entry from the ssh hosts file. # Usage: kill_known_host [options] | # Options: -n Only report key; don't delete it. # -p Allow partial match. # Example: kill_known_host -p www # Remove all keys with hostname beginning www. # Exits: 0 on success. # 1 on error. # 111 if the entry didn't exist. # Notes: Based on Jim's kill-known-host. # use Getopt::Std; my $KNOWN_HOSTS = "$ENV{HOME}/.ssh/known_hosts"; my $SCRATCH = "$KNOWN_HOSTS.$$"; our $opt_n, $opt_p; getopts("np"); # Check args. unless (@ARGV) { print STDERR "Usage: kill_known_host [options] |\n"; print STDERR "Options: -n Only report key; don't delete it.\n"; print STDERR " -p Allow partial match.\n"; print STDERR "Example: kill_known_host -p www\n"; print STDERR " Remove all keys with hostname beginning www.\n"; print STDERR "Exits: 0 on success.\n"; print STDERR " 1 on error.\n"; print STDERR " 111 if the entry didn't exist.\n"; exit 1; } my $host = shift; my $dotstar = $opt_p ? '[^\s,]*' : ''; my $re; # Check if it's an IP or a hostname. if ($host =~ /^[1-9]\d{0,2}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/) { $re = "^([^\\s]+,)?$host$dotstar\\s"; } else { $re = "^$host$dotstar\[\\s,]"; } # Read known hosts. open IN, "< $KNOWN_HOSTS" or die "Can't read known_hosts: $!\n"; # Open scratch file. open OUT, "> $SCRATCH" or die "Can't open scratch file: $!\n" unless $opt_n; my ($in, $out) = (0, 0); while () { $in++; if (/$re/) { if ($opt_n) { $out++; print; } else { next } } unless ($opt_n) { print OUT; $out++; } } # Cleanup. close IN; if ($opt_n) { exit 111 unless $out; exit 0; } close OUT; # Move hosts. rename $SCRATCH, $KNOWN_HOSTS or die "Can't rename $KNOWN_HOSTS: $!\n"; exit 111 if $in == $out; exit 0;