#!/usr/local/bin/perl # little script i wrote to automate this, values can be changed and even added, just stick to same structure # and you wont have a problem ;> # # requires IO::CaptureOutput module, to install: perl -MCPAN -e 'install IO::CaptureOutput' # # craftsmanship by acidrein. (ar) 20/03/2008. use strict; use warnings; use vars qw(%netctl %vmemctl %store); use IO::CaptureOutput qw(capture capture_exec); our $uid = getlogin(); our $vuid = "root"; our $sysctl = "/sbin/sysctl"; %netctl = ( 'net.ipv4.tcp_rmem' => '8192 1677722 16777216', 'net.ipv4.tcp_wmem' => '4096 1468006 14680064', 'net.ipv4.tcp_mem' => '94368 125824 188736', 'net.core.rmem_default' => '2097152', 'net.core.wmem_default' => '2097152', 'net.core.rmem_max' => '16777216', 'net.core.wmem_max' => '14680064', 'net.core.optmem_max' => '2097152', 'net.core.netdev_max_backlog' => '4500', 'net.core.somaxconn' => '512', 'net.ipv4.tcp_sack' => '1', 'net.ipv4.tcp_fack' => '1', 'net.ipv4.tcp_ecn' => '1', 'net.ipv4.tcp_no_metrics_save' => '1', 'net.ipv4.tcp_max_syn_backlog' => '1024', 'net.ipv4.tcp_fin_timeout' => '25', 'net.ipv4.tcp_keepalive_time' => '1800', 'net.ipv4.tcp_max_tw_buckets' => '256000', 'net.ipv4.tcp_timestamps' => '1', 'net.ipv4.tcp_workaround_signed_windows' => '0', 'net.ipv4.tcp_syncookies' => '1', 'net.ipv4.conf.all.rp_filter' => '1', 'net.ipv4.conf.default.rp_filter' => '1', 'net.ipv4.conf.default.arp_filter' => '1', 'net.ipv4.conf.all.arp_filter' => '1', ); %vmemctl = ( 'vm.min_free_kbytes' => '65536', 'vm.dirty_background_ratio' => '4', 'vm.dirty_ratio' => '67', 'vm.dirty_writeback_centisecs' => '650', 'vm.dirty_expire_centisecs' => '5000', 'vm.overcommit_memory' => '2', ); %store = (); sub dec2bin { my $str = unpack("B32", pack("N", shift)); # remove leading zeros $str =~ s/^0+(?=\d)//; return $str; } sub bin2dec { return unpack("N", pack("B32", substr("0" x 32 . shift, -32))); } sub do_sysctl($@) { my ($skey, $sval) = @_; my ($tmpout, $tmperr, $i, $av, $tmplen, $tmpslen, $tmpbuf); my (@ma, @sa, @tmpb, @tmpe, @abn) = (); # do read from sysctl bit to test current values ($tmpout, $tmperr) = capture_exec("$sysctl $skey"); # check error status and search for unknown in stderr if ($? != 0) { if ($tmperr =~ /unknown/) { return 127; } return $?; } # find index of where '=' is in stdout string, incr by +1 which is first char after $tmplen = length($tmpout); $tmpslen = index($tmpout,'=') + 1; # use index value to get new start point of tmpout $tmpout = substr($tmpout, $tmpslen, $tmplen - $tmpslen); # clean up excess whitepsaces by matching word chars @ma = $tmpout =~ m/\b([\w]{1,})\b/g; if (scalar(@ma) == 0) { return 127; } $av = scalar(@ma); if ($av > 1) { @sa = split(' ', $sval); # bn is root 2, @abn is array holding binary values my ($bi,$zbn) = (0,0000); my $bn = 2; for ( $bi = 0; $bi < $av; $bi++ ) { # take power of 2 and convert to bin for true false compare my $tdn = $bn << ($bi + 1); my $tbn = dec2bin($tdn); if ($sa[$bi] == $ma[$bi]) { push(@abn, $tbn); } else { push(@abn, dec2bin($zbn)); } } $i = 0; for ( $bi = 0; $bi < $av; $bi++ ) { if (bin2dec($abn[$bi]) != 0) { $i++; } } if ($av == $i) { return 1; } #printf("%s -w %s=\"%s\"\n", $sysctl, $skey, $sval); system("$sysctl -w $skey=$sval"); if ($? >= 0) { return $?; } } else { # join our matches with single whitespace now $i = join(' ', @ma); if ($sval != $i) { #printf("%s -w %s=%s\n", $sysctl, $skey, $sval); system("$sysctl -w $skey=$sval"); if ($? >= 0) { return $?; } } } return 1; } sub chkexit($@$) { my ($key,$val,$exit) = @_; # check return values, 0 = success, 1 = same value, 127 = value non-existant if ($exit == 0) { printf("%s has been changed to %s.\n", $key, $val); } elsif ($exit == 1) { #printf("%s is same as current value, skipping.\n", $key); } elsif ($exit == 127) { printf("%s no existo on your systemo, adios.\n", $key); } else { printf("unknown exit code from sysctl, check man. exit code: '%d'\n", $exit); } } sub main { my $vret; # check uid current if ($uid !~ m/$vuid/) { printf("You must be logged in as %s to change these settings, %s is not valid\n", $vuid, $uid); return 0; } # create local hash array with pointers to global hash arrays my %ht = ( hn => \%netctl, hv => \%vmemctl, ); # we cant pass the physical hash to the for loop so we create a pointer to it my $hptr = \%ht; # loop through all the keys of the hashes yay foreach my $k (keys %{$hptr}) { my $kv = $hptr->{$k}; foreach my $hkey (sort keys %{$kv}) { my $hval = $kv->{$hkey}; # pass key and value to function to test and write sysctl stuff $vret = do_sysctl($hkey, ${hval}); chkexit($hkey,$hval,$vret); } } return 0; } main();