@@ -19,6 +19,8 @@ ALL_ARGS="$@"
19
19
OPTIONS_ERROR_EXIT=" false"
20
20
DEFAULT_LIST_LIMIT=50
21
21
DEFAULT_CONNECTION_TIMEOUT=10
22
+ DEFAULT_PG_PORT=5432
23
+ DEFAULT_SSH_PORT=22
22
24
LARGE_DB_ITEMS_COUNT=100000
23
25
AVAILABLE_MODES=(" collect" " process" " upload" " help" " run" )
24
26
@@ -377,6 +379,58 @@ validate_arg_type() {
377
379
fi
378
380
}
379
381
382
+ # ######################################
383
+ # Generate psql command
384
+ # Globals:
385
+ # PSQL_CONN_OPTIONS, HOST, OPTIONS_ERROR_EXIT
386
+ # USERNAME, PGPASSWORD, DBNAME, STIMEOUT
387
+ # Arguments:
388
+ # None
389
+ # Returns:
390
+ # None
391
+ # ######################################
392
+ generate_psql_cmd () {
393
+ local pg_port=$DEFAULT_PG_PORT
394
+ if [[ " $PGPORT " != " None" ]]; then
395
+ pg_port=$PGPORT
396
+ fi
397
+
398
+ # custom UNIX domain socket directory for PostgreSQL
399
+ local psql_unix_socket_option=" "
400
+ if [[ " ${PGSOCKET} " != " None" ]]; then
401
+ psql_unix_socket_option=" --host '${PGSOCKET} ' "
402
+ fi
403
+
404
+ # custom psql binary path support
405
+ local psql_bin=" psql"
406
+ if [[ " ${PSQLBINARY} " != " None" ]]; then
407
+ psql_bin=" ${PSQLBINARY} "
408
+ fi
409
+
410
+ # generate or not PGPASSWORD string (for substitution)
411
+ if [[ ! -z ${PGPASSWORD+x} ]]; then
412
+ local pgpas_subst=" PGPASSWORD=\" ${PGPASSWORD} \" " # whitespace in the end of the string
413
+ else
414
+ local pgpas_subst=" "
415
+ fi
416
+
417
+ # use default Postgres username or not
418
+ local user_substr=" "
419
+ if [[ ! -z ${USERNAME+x} ]]; then
420
+ user_substr=" -U \" ${USERNAME} \" "
421
+ fi
422
+
423
+ # Construct _PSQL macro for usage inside the check scripts
424
+ export PSQL_CONN_OPTIONS=" --port=${pg_port} --dbname=${DBNAME} ${user_substr} ${psql_unix_socket_option} "
425
+ psql_command=" ${pgpas_subst}${psql_bin} -1 -X -At -q -v ON_ERROR_STOP=1 -P pager=off ${PSQL_CONN_OPTIONS} "
426
+ export _PSQL_NO_TIMEOUT=" PGAPPNAME=checkup ${psql_command} "
427
+ export _PSQL=" PGAPPNAME=checkup PGOPTIONS=\" -c statement_timeout=${STIMEOUT} s\" ${psql_command} "
428
+
429
+ dbg " "
430
+ dbg " PSQL_CONN_OPTIONS: $PSQL_CONN_OPTIONS "
431
+ dbg " "
432
+ }
433
+
380
434
# ######################################
381
435
# Validate arguments and and save input variables
382
436
# Globals:
@@ -410,18 +464,20 @@ validate_args() {
410
464
done
411
465
412
466
# fill default (not given) psql connection related variables
413
- [[ " ${PGPORT} " = " None" ]] && export PGPORT=5432
414
467
[[ " ${DBNAME} " = " None" ]] && export DBNAME=postgres
415
468
[[ " ${STIMEOUT} " = " None" ]] && export STIMEOUT=30 # statement timeout
416
469
[[ " ${USERNAME} " = " None" ]] && export USERNAME=" "
417
470
[[ " ${LISTLIMIT} " = " None" ]] && export LISTLIMIT=${DEFAULT_LIST_LIMIT}
418
471
[[ " ${CONNTIMEOUT} " = " None" ]] && export CONNTIMEOUT=${DEFAULT_CONNECTION_TIMEOUT} # connection timeout
472
+
419
473
if [[ " ${MODE} " = " None" ]]; then
420
474
export MODE=" run"
421
475
ARG_VALUE[0]=" run"
422
476
ARG_IS_GIVEN[0]=" true"
423
477
fi
424
478
479
+ generate_psql_cmd
480
+
425
481
if ([[ " $HTML " == " true" ]] || [[ " $PDF " == " true" ]]); then
426
482
PANDOC=$( which pandoc || echo -n " 0" ) ;
427
483
if [[ " $PANDOC " == " 0" ]]; then
@@ -448,41 +504,6 @@ validate_args() {
448
504
fi
449
505
fi
450
506
451
- # custom UNIX domain socket directory for PostgreSQL
452
- local psql_unix_socket_option=" "
453
- if [[ " ${PGSOCKET} " != " None" ]]; then
454
- psql_unix_socket_option=" --host '${PGSOCKET} ' "
455
- fi
456
-
457
- # custom psql binary path support
458
- local psql_bin=" psql"
459
- if [[ " ${PSQLBINARY} " != " None" ]]; then
460
- psql_bin=" ${PSQLBINARY} "
461
- fi
462
-
463
- # generate or not PGPASSWORD string (for substitution)
464
- if [[ ! -z ${PGPASSWORD+x} ]]; then
465
- local pgpas_subst=" PGPASSWORD=\" ${PGPASSWORD} \" " # whitespace in the end of the string
466
- else
467
- local pgpas_subst=" "
468
- fi
469
-
470
- # use default Postgres username or not
471
- local user_substr=" "
472
- if [[ ! -z ${USERNAME+x} ]]; then
473
- user_substr=" -U \" ${USERNAME} \" "
474
- fi
475
-
476
- # Construct _PSQL macro for usage inside the check scripts
477
- export PSQL_CONN_OPTIONS=" --port=${PGPORT} --dbname=${DBNAME} ${user_substr} ${psql_unix_socket_option} "
478
- psql_command=" ${pgpas_subst}${psql_bin} -1 -X -At -q -v ON_ERROR_STOP=1 -P pager=off ${PSQL_CONN_OPTIONS} "
479
- export _PSQL_NO_TIMEOUT=" PGAPPNAME=checkup ${psql_command} "
480
- export _PSQL=" PGAPPNAME=checkup PGOPTIONS=\" -c statement_timeout=${STIMEOUT} s\" ${psql_command} "
481
-
482
- dbg " "
483
- dbg " PSQL_CONN_OPTIONS: $PSQL_CONN_OPTIONS "
484
- dbg " "
485
-
486
507
# error if mandatory options are not set (print as a stack)
487
508
local buf=" "
488
509
for i in $( seq 0 ${CLI_ARGS_POSSIBLE} ) ; do
@@ -496,6 +517,34 @@ validate_args() {
496
517
fi
497
518
fi
498
519
done
520
+ if [[ " $HOST " == " None" ]] && [[ " $SSHHOST " == " None" ]] &&
521
+ [[ " $PGHOST " == " None" ]] && ([[ " $MODE " == " collect" ]] || [[ " $MODE " == " run" ]]) ; then
522
+ buf=" $buf
523
+ at least one of options '--hostname', '--ssh-hostname' or '--pg-hostname' must be set"
524
+ # mandatory option '--hostname' is not set"
525
+ need_fail_exit=true
526
+ OPTIONS_ERROR_EXIT=true
527
+ fi
528
+
529
+ local hosts=0
530
+ [[ " $SSHHOST " != " None" ]] && hosts=$(( hosts + 1 ))
531
+ [[ " $PGHOST " != " None" ]] && hosts=$(( hosts + 1 ))
532
+ [[ " $HOST " != " None" ]] && hosts=$(( hosts + 1 ))
533
+
534
+ if [[ $hosts -gt 1 ]]; then
535
+ buf=" $buf
536
+ only one of options '--hostname', '--ssh-hostname' or '--pg-hostname' may be used"
537
+ need_fail_exit=true
538
+ OPTIONS_ERROR_EXIT=true
539
+ fi
540
+
541
+ if [[ " $SSHPORT " != " None" ]] && ([[ " $PGHOST " != " None" ]] || [[ " $HOST " != " None" ]]) ; then
542
+ buf=" $buf
543
+ '--ssh-port' may be used only with '--ssh-hostname'"
544
+ need_fail_exit=true
545
+ OPTIONS_ERROR_EXIT=true
546
+ fi
547
+
499
548
if [[ " $need_fail_exit " = " true" ]]; then
500
549
usage " $buf " " 1"
501
550
fi
@@ -700,7 +749,7 @@ is_in_recovery() {
700
749
dbg " host $HOST is 'standby'"
701
750
return 0
702
751
else
703
- msg " ERROR: Cannot connect to the host: ${HOST} . "
752
+ msg " ERROR: Cannot connect to the host: ${HOST} "
704
753
exit 1
705
754
fi
706
755
return 13
@@ -938,6 +987,73 @@ glue_md_reports() {
938
987
fi
939
988
}
940
989
990
+ # ######################################
991
+ # Configure SSH connection
992
+ # Globals:
993
+ # CHECK_HOST_CMD, SSH_SUPPORT, SSHPORT, PORT
994
+ # Arguments:
995
+ # (text) host name
996
+ # Returns:
997
+ # Integer
998
+ # ######################################
999
+ configure_ssh_connection () {
1000
+ hostname=$1
1001
+
1002
+ if [[ " $SSHPORT " == " None" ]]; then
1003
+ if [[ " $PORT " != " None" ]]; then
1004
+ SSHPORT=$PORT
1005
+ else
1006
+ SSHPORT=$DEFAULT_SSH_PORT
1007
+ fi
1008
+ fi
1009
+
1010
+ if native_hostname=$( ssh -p ${SSHPORT} -o ConnectTimeout=10 ${hostname} " hostname" 2> /dev/null) ; then
1011
+ # ssh to remote host and use local psql (default)
1012
+ export CHECK_HOST_CMD=" ssh ${hostname} "
1013
+ export SSH_SUPPORT=" true"
1014
+ return 0
1015
+ else
1016
+ return 1
1017
+ fi
1018
+ }
1019
+
1020
+ # ######################################
1021
+ # Configure psql connection
1022
+ # Globals:
1023
+ # CHECK_HOST_CMD, SSH_SUPPORT, PGPORT, PORT
1024
+ # Arguments:
1025
+ # (text) host name
1026
+ # Returns:
1027
+ # Integer
1028
+ # ######################################
1029
+ configure_psql_connection () {
1030
+ hostname=$1
1031
+
1032
+ if [[ " $PGPORT " == " None" ]]; then
1033
+ if [[ " $PORT " != " None" ]]; then
1034
+ PGPORT=$PORT
1035
+ else
1036
+ PGPORT=$DEFAULT_PG_PORT
1037
+ fi
1038
+ generate_psql_cmd
1039
+ fi
1040
+
1041
+ export CHECK_HOST_CMD=" bash -e -u -o pipefail -c"
1042
+
1043
+ # use local psql and connect to remote postgres without ssh
1044
+ local re=" 127\.0"
1045
+ if [[ " ${hostname} " =~ $re || " ${hostname} " = " localhost" ]]; then
1046
+ # keep _PSQL and _PSQL_NO_TIMEOUT as is, use UNIX domain socket for psql
1047
+ true
1048
+ else
1049
+ # use TCP for psql
1050
+ export _PSQL=" PGCONNECT_TIMEOUT=${CONNTIMEOUT} ${_PSQL} -h ${hostname} "
1051
+ export _PSQL_NO_TIMEOUT=" ${_PSQL_NO_TIMEOUT} -h ${hostname} "
1052
+ fi
1053
+
1054
+ export SSH_SUPPORT=" false"
1055
+ }
1056
+
941
1057
# ######################################
942
1058
# Check rights, set global variables, etc.
943
1059
# Globals:
@@ -949,31 +1065,34 @@ glue_md_reports() {
949
1065
# Integer
950
1066
# ######################################
951
1067
host_pre_start_checks () {
952
- # choise host connection command
953
- # while checking ssh support
954
- if native_hostname=$( ssh $HOST " hostname" 2> /dev/null) ; then
955
- # ssh to remote host and use local psql (default)
956
- export CHECK_HOST_CMD=" ssh ${HOST} "
957
- export SSH_SUPPORT=" true"
1068
+ if [[ " $SSHHOST " != " None" ]]; then
1069
+ # ssh mode
1070
+ if configure_ssh_connection $SSHHOST ; then
1071
+ msg " Connection type (specified): SSH ($SSHHOST :$SSHPORT )"
1072
+ export HOST=$SSHHOST
1073
+ else
1074
+ msg " Connection type (specified): SSH ($SSHHOST :$SSHPORT )"
1075
+ msg " ERROR: Cannot connect to the host: ${SSHHOST} :${SSHPORT} via SSH"
1076
+ exit 1
1077
+ fi
1078
+ elif [[ " $PGHOST " != " None" ]]; then
1079
+ # psql mode
1080
+ if configure_psql_connection $PGHOST ; then
1081
+ msg " Сonnection type (specified): PostgreSQL ($PGHOST :$PGPORT )"
1082
+ export HOST=$PGHOST
1083
+ fi
958
1084
else
959
- # swap ssh with bash
960
- export CHECK_HOST_CMD=" bash -e -u -o pipefail -c"
961
-
962
- # use local psql and connect to remote postgres without ssh
963
- local re=" 127\.0"
964
- if [[ " ${HOST} " =~ $re || " ${HOST} " = " localhost" ]]; then
965
- # keep _PSQL and _PSQL_NO_TIMEOUT as is, use UNIX domain socket for psql
966
- true
1085
+ # auto detect connection command
1086
+ if configure_ssh_connection $HOST ; then
1087
+ msg " Connection type (auto-detected): SSH ($HOST :$SSHPORT )"
967
1088
else
968
- # use TCP for psql
969
- export _PSQL= " PGCONNECT_TIMEOUT= ${CONNTIMEOUT} ${_PSQL} -h ${ HOST} "
970
- export _PSQL_NO_TIMEOUT= " ${_PSQL_NO_TIMEOUT} -h ${ HOST} "
1089
+ msg " Cannot connect to the host: ${HOST} : ${SSHPORT} via SSH "
1090
+ configure_psql_connection $ HOST;
1091
+ msg " Connection type (auto-detected): PostgreSQL ( $ HOST: $PGPORT ) "
971
1092
fi
972
-
973
- export SSH_SUPPORT=" false"
1093
+ export HOST
974
1094
fi
975
1095
976
- export HOST
977
1096
dbg " CHECK_HOST_CMD: '${CHECK_HOST_CMD} '"
978
1097
dbg " HOST: '${HOST} '"
979
1098
dbg " _PSQL: '${_PSQL} '"
@@ -1132,8 +1251,6 @@ run_checks() {
1132
1251
test -d " ${PROJECT_DIR} " || mkdir -p " ${PROJECT_DIR} "
1133
1252
1134
1253
# perform all checks from './resources/checks/' directory
1135
- msg
1136
- msg " ########## Perform checks for host '${HOST} ':"
1137
1254
if is_in_recovery; then
1138
1255
ROLE=" standby"
1139
1256
else
@@ -1151,6 +1268,8 @@ run_checks() {
1151
1268
export IS_LARGE_DB=0
1152
1269
fi
1153
1270
1271
+ msg
1272
+ msg " ########## Perform checks for host '${HOST} ':"
1154
1273
local output
1155
1274
for CURRENT_CHECK_FNAME in " ${SCRIPT_DIR} " /resources/checks/* _* .sh; do
1156
1275
[[ -e " ${CURRENT_CHECK_FNAME} " ]] || continue
@@ -1332,8 +1451,13 @@ run_upload() {
1332
1451
1333
1452
# ######## COMMANDS WRAPPERS ###########
1334
1453
ssh () {
1454
+ local ssh_port=$DEFAULT_SSH_PORT
1455
+ if [[ " $SSHPORT " != " None" ]]; then
1456
+ ssh_port=$SSHPORT
1457
+ fi
1458
+
1335
1459
local ssh_timeout_options=" -o ConnectTimeout=${CONNTIMEOUT} -o ServerAliveInterval=6 -o ServerAliveCountMax=5"
1336
- local ssh_options=" -o StrictHostKeyChecking=no -o Compression=no -o BatchMode=yes ${ssh_timeout_options} "
1460
+ local ssh_options=" -p ${ssh_port} - o StrictHostKeyChecking=no -o Compression=no -o BatchMode=yes ${ssh_timeout_options} "
1337
1461
1338
1462
local ssh_master_socket=' /tmp/ssh_pg_check_%h_%p_%r'
1339
1463
local ssh_master_options=" -o ControlMaster=auto -o ControlPersist=yes"
0 commit comments