Skip to content

Commit

Permalink
add support for PGHOST, PGPORT, PGDATABASE, PGUSER, PGPASSWORD and ~/… (
Browse files Browse the repository at this point in the history
#17)

* add support for PGHOST, PGPORT, PGDATABASE, PGUSER, PGPASSWORD and ~/.pgpass
  • Loading branch information
jfcoz authored Dec 19, 2017
1 parent a05850e commit 12c250f
Show file tree
Hide file tree
Showing 3 changed files with 102 additions and 10 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ install:
before_script:
- psql -c 'create database travis_ci_test;' -U postgres

script: "./postgresqltuner.pl --host=localhost --user=postgres --database=travis_ci_test"
script: "./postgresqltuner.pl --host=localhost --user=postgres --database=travis_ci_test --password=''"

notifications:
recipients:
Expand Down
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,9 @@ postgresqltuner.pl --host=dbhost --database=testdb --user=username --password=qw
postgres$ postgresqltuner.pl --host=/var/run/postgresql # PostgreSQL socket directory
```

If available postgresqltuner.pl will use standard PostgreSQL variables like `PGHOST`, `PGPORT`, `PGDATABASE`, `PGUSERNAME`, and password from `~/.pgpass` file.


### With docker

- Via network :
Expand All @@ -164,6 +167,13 @@ docker run -it --rm --link your-postgresql-container:dbhost jfcoz/postgresqltune

When using it remotly, postgresqltuner.pl will use ssh to collect OS informations. You must configure ssh to connect to remote host with private key authentication.

### Passwords

For better security use a `~/.pgpass` file containing passwords, so password will not be saved in the shell history nor in the process list. [.pgpass documentation](https://www.postgresql.org/docs/current/static/libpq-pgpass.html)
```
host:port:database:username:password
```

## Options

- Average number of work_mem buffer per connection :
Expand Down
100 changes: 91 additions & 9 deletions postgresqltuner.pl
Original file line number Diff line number Diff line change
Expand Up @@ -47,26 +47,27 @@
exit 1;
}

my $script_version="0.0.10";
my $script_version="0.0.11";
my $script_name="postgresqltuner.pl";
my $min_s=60;
my $hour_s=60*$min_s;
my $day_s=24*$hour_s;
my $os_cmd_prefix='';

my $host='/var/run/postgresql';
my $username='postgres';
my $password='';
my $database="template1";
my $port=5432;
my $host=undef;
my $username=undef;
my $password=undef;
my $database=undef;
my $port=undef;
my $pgpassfile=$ENV{HOME}.'/.pgpass';
my $help=0;
my $work_mem_per_connection_percent=150;
GetOptions (
"host=s" => \$host,
"user=s" => \$username,
"username=s" => \$username,
"pass=s" => \$password,
"password=s" => \$password,
"pass:s" => \$password,
"password:s" => \$password,
"db=s" => \$database,
"database=s" => \$database,
"port=i" => \$port,
Expand All @@ -79,12 +80,78 @@
usage(0);
}

# host
if (!defined($host)) {
if (defined($ENV{PGHOST})) {
$host=$ENV{PGHOST};
} else {
$host='/var/run/postgresql';
}
}

# port
if (!defined($port)) {
if (defined($ENV{PGPORT})) {
$port=$ENV{PGPORT};
} else {
$port=5432;
}
}

# database
if (!defined($database)) {
if (defined($ENV{PGDATABASE})) {
$database=$ENV{PGDATABASE};
} else {
$database='template1';
}
}

# user
if (!defined($username)) {
if (defined($ENV{PGUSER})) {
$username=$ENV{PGUSER};
} else {
$username='postgres';
}
}

# if needed, get password from ~/.pgpass
if (!defined($password)) {
if (defined($ENV{PGPASSWORD})) {
$password=$ENV{PGPASSWORD};
} else {
if (defined($ENV{PGPASSFILE})) {
$pgpassfile=$ENV{PGPASSFILE};
}
}

if (open(PGPASS,'<',$pgpassfile)) {
while (my $line=<PGPASS>) {
chomp($line);
next if $line =~ /^\s*#/;
my ($pgp_host,$pgp_port,$pgp_database,$pgp_username,$pgp_password,$pgp_more)=split(/(?<!\\):/,$line); # split except after escape char
next if (!defined($pgp_password) or defined($pgp_more)); # skip malformated line
next if (!pgpass_match('host',$host,$pgp_host));
next if (!pgpass_match('port',$port,$pgp_port));
next if (!pgpass_match('database',$database,$pgp_database));
next if (!pgpass_match('username',$username,$pgp_username));
$password=pgpass_unescape($pgp_password);
last;
}
close(PGPASS);
}
}

usage(1) if (!defined($host) or !defined($username) or !defined($password));

sub usage {
my $return=shift;
print STDERR "usage: $script_name --host [ hostname | /var/run/postgresql ] [--user username] [--password password] [--database database] [--port port] [--wmp 150]\n";
print STDERR "\twmp: average number of work_mem buffers per connection in percent (default 150)\n";
print STDERR "If available connection informations can be read from \$PGHOST, \$PGPORT, \$PGDATABASE, \$PGUSER, \$PGPASSWORD\n";
print STDERR "For security reasons, prefer usage of password in ~/.pgpass\n";
print STDERR "\thost:port:database:username:password\n";
print STDERR " --wmp: average number of work_mem buffers per connection in percent (default 150)\n";
exit $return;
}

Expand Down Expand Up @@ -887,3 +954,18 @@ sub print_advices {
print color("green")."Everything is good".color("reset")."\n";
}
}

sub pgpass_match {
my ($type,$var,$pgp_var)=@_;
$pgp_var=pgpass_unescape($pgp_var);
return 1 if $pgp_var eq '*';
return 1 if $pgp_var eq $var;
return 1 if $type eq 'host' and $pgp_var eq 'localhost' and $var=~m/^\//; # allow sockets if host=localhost
return 0;
}

sub pgpass_unescape {
my ($value)=@_;
$value=~s/\\(.)/$1/g;
return $value;
}

0 comments on commit 12c250f

Please sign in to comment.