Skip to content

Allow script to run without init system (in containers) #38

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 0 additions & 18 deletions README

This file was deleted.

75 changes: 75 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# postgresql-setup

## Requires

### BuildRequires
- make
- m4
- docbook-utils
- help2man
- elinks (pretty README.rpm-dist)
- postgresql-server (detect current version)

### Requires
- coreutils

### Suggested BuildRequires
- util-linux (mountpoint utility)

### Maintainer's BuildRequires
- autoconf
- automake
- autoconf-archive

## Usage
This script is used as a wrapper around PostgreSQL initialization and upgrade
commands. It also parses init system service files and/or environment files to
correctly find datadir based on current system.

### Initialization
To initialize new PostgreSQL data directory use `./postgresql-setup --initdb`.

### Upgrade
To upgrade existing PostgreSQL data directory to use newer PostgreSQL version
use `./postgresql-setup --upgrade`.

If your distribution doesn't include this
script with PostgreSQL and you are using this on your own, please update
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do I understand it correctly that you mean users who want to use it on other distributions?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, from what I understood this script is completely distro/os agnostic (as long as u have bash) and you could configure the paths.

And with the addition of not being dependent on systemd you have even more possibilities with this script. I mean, theoretically it could even be used on macOS with bash and postgresql installed (via brew, for example). Only thing that you would need is to fix the paths via autotools config (maybe something is hardcoded somewhere, but mostly just autotools).

`./etc/postgresql-setup/upgrade/postgresql.conf` to reflect your setup.

### Running without systemd/init system
Your setup might not include systemd as the init system or include any
init system at all. This would be the case in most of the base container images
for example. This script will try to compensate by parsing systemd
service file in preconfigured path directly. By default the path is
`/lib/systemd/system`.

If there is no systemd service file, or for whatever reason the script is unable
to find valid PostgreSQL data directory, you can still provide PostgreSQL data
directory path manually by using `--datadir` argument. For example when
initializing new data directory use `postgresql-setup --initdb --datadir=/my/path`.

This feature is most beneficial when using this script inside container images,
as it gives you the most control with least dependencies.

## Maintainer notes
Be careful about paths. You might need to tweak paths either in the configure
files, or in code based on your environment.
- Line 49 of `./bin/postgresql-setup.in` in function `builddir_source ()` has to
be changed to location of your project otherwise you won't be able to run your
build without full installation into system paths
- For example line should be `. "/postgresql-setup/$file"` if your
working project is located at `/postgresql-setup`
- *Do NOT commit/merge this change*

### Build instructions
1. `autoreconf -vfi`
2. `./configure --prefix=/usr`
- Prefix needed for fedora environment - one of the path tweaks that are needed
3. `make`

After aforementioned steps, you should be able to run freshly built
postgresql-setup script directly from /bin folder in this repo.

If no init system is present, PostgreSQL server can be run after initialization
via `/usr/bin/pg_ctl -D /var/lib/pgsql/data -l /var/lib/pgsql/logfile start`
89 changes: 68 additions & 21 deletions bin/postgresql-setup.in
Original file line number Diff line number Diff line change
Expand Up @@ -85,16 +85,11 @@ Options:
string). When no UNIT_NAME is explicitly passed,
the 'postgresql' string is used by default.
--port=PORT port where the initialized server will listen for
connections"

test 0 -eq @WANT_SYSVINIT@ && \
USAGE_STRING+="
--new-systemd-unit We dropped this option for security reasons.
Nowadays, please use the root-only script
@sbindir@/@NAME_BINARYBASE@-new-systemd-unit.
--datadir Dropped with --new-systemd-unit."

USAGE_STRING+="
connections
--datadir Override automatic detection of PostgreSQL data
directory. If your system is using systemd as init
system, it is advisable to change data directory
path in service file instead.
--upgrade-from-unit=UNIT Select proper unit name to upgrade from. This
has similar semantics as --unit option.
--upgrade-ids Print list of available IDs of upgrade scenarios to
Expand Down Expand Up @@ -401,6 +396,37 @@ handle_service_env()
done
}

handle_service_file()
{
local service_file="$1"
local line var_name var_value
debug "Parsing ${service_file}"
local systemd_env="$(cat "${service_file}")" \
|| { return; }
Comment on lines +404 to +405
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is very strange syntax? Might be ok to keep though, consider adding comment.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's reused from other similar functions as the one exactly above 'handle_service_env()'. It is probably more readable to just pipe the file using << directly into the loop. But not sure really, I just tried to be consistent, even tho in the other functions we are not working with files at all - so we wouldn't be able to use << there.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cat is fine, although, yes, you should use pipes, that's what the general guidelines say, I was pointing at the { return; } as it might not be immediately obvious.


while IFS= read -r line; do
# Only lines starting with Environment=
[[ "$line" =~ ^Environment= ]] || continue

# Remove 'Environment=' prefix
line="${line#Environment=}"

for env_val in $line; do
var_name="${env_val%%=*}"
var_value="${env_val#*=}"
debug "Found environment variable: $var_name=$var_value"

case "$var_name" in
PGDATA)
unit_pgdata="$var_value"
;;
PGPORT)
unit_pgport="$var_value"
;;
esac
done
done <<< "$systemd_env"
}

handle_envfile()
{
Expand All @@ -418,6 +444,7 @@ handle_envfile()
# Note that the env file parser in systemd does not perform exactly the
# same job.
unset PGPORT PGDATA
# Source the file, loading the variables in it
. "$file"
envfile_pgdata="$PGDATA"
envfile_pgport="$PGPORT"
Expand Down Expand Up @@ -503,18 +530,35 @@ service_configuration()
&& set_var "$datavar" "@PGDATADIR@"
handle_envfile "@initscriptsconfdir@/$service"
else
# We ship two service files, @NAME_SERVICE@.service and
# @NAME_SERVICE@@.service. The former has PGDATA set by default
# similarly to sysvinit case.
handle_service_env "$service"
handle_service_envfiles "$option_mode" "$service"
if grep -q systemd /proc/1/comm; then
# If booted with systemd as PID 1, we try to find the variables
# using systemctl show -p Environment= @NAME_SERVICE@.service
# We ship two service files, @NAME_SERVICE@.service and
# @NAME_SERVICE@@.service. The former has PGDATA set by default
# similarly to sysvinit case.
debug "System booted with systemd as PID 1, using systemctl to find"\
"service configuration for $service"
handle_service_env "$service"
handle_service_envfiles "$option_mode" "$service"
else
# If not booted with systemd, we try to find the service file in
# predefined path and parse it manually.
warn "System not booted with systemd as PID 1. Manually parsing service"\
"file @INIT_SYSTEM_SERVICE_PATH@/$service.service"
handle_service_file "@INIT_SYSTEM_SERVICE_PATH@/$service.service"
fi
fi

# EnvironmentFile beats Environment configuration in systemd. In sysvinit
# there is no "unit_pgdata". So make sure the envfile_gpdata is used later
# than unit_pgdata.
test -n "$unit_pgdata" && set_var "$datavar" "$unit_pgdata"
test -n "$envfile_pgdata" && set_var "$datavar" "$envfile_pgdata"
# If the user specified --datadir, take priority over all
if [ -n "${option_datadir}" ]; then
info $"Using datadir from --datadir: $option_datadir"
set_var "$datavar" "$option_datadir"
fi

# skip for the first run
test initdb = "$mode" && return
Expand Down Expand Up @@ -571,6 +615,7 @@ option_service="@NAME_SERVICE@"
option_port=
option_debug=0
option_upgradefrom_unit=
option_datadir=

# Content of EnvironmentFile= files fills those:
envfile_pgdata=
Expand Down Expand Up @@ -626,10 +671,9 @@ while true; do
shift 2
;;

--datadir|--new-systemd-unit)
error $"Removed option --new-systemd-unit/--datadir, please use"
error_q $"@sbindir@/@NAME_BINARYBASE@-new-systemd-unit script"
exit 1
--datadir)
option_datadir="$2"
shift 2
;;

--debug)
Expand Down Expand Up @@ -698,7 +742,7 @@ debug "service name: $option_service"
service_configuration initdb pgdata UNUSED "$option_service"

test "$pgdata" = default \
&& die $"no db datadir (PGDATA) configured for '$option_service$srvsuff' unit"
&& die $"no db datadir (PGDATA) found, try using --datadir option"

[[ "$pgdata" =~ ^/.* ]] \
|| die $"the PostgreSQL datadir not absolute path: '$pgdata', try --debug"
Expand Down Expand Up @@ -775,7 +819,10 @@ fi

## LAST CHECK THE SETUP ##

check_daemon_reload
if grep -q systemd /proc/1/comm; then
# Check only if we are running under systemd.
check_daemon_reload
fi

# These variables are read by underlying utilites, rather export them.
export PGDATA=$pgdata
Expand Down
16 changes: 10 additions & 6 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,11 @@ _AX_TEXT_TPL_SUBST([TEST_GEN_FILES_LIST], [.generated_files])

WANT_SYSVINIT=0
INIT_SYSTEM=systemd
INIT_SYSTEM_SERVICE_PATH=/lib/systemd/system
test -d /usr/lib/systemd/system/ || {
INIT_SYSTEM=sysvinit
WANT_SYSVINIT=1
INIT_SYSTEM_SERVICE_PATH=
}
AM_CONDITIONAL([WANT_SYSVINIT], [test "$WANT_SYSVINIT" -eq 1])
_AX_TEXT_TPL_SUBST([WANT_SYSVINIT])
Expand Down Expand Up @@ -221,6 +223,7 @@ _AX_TEXT_TPL_SUBST([NAME_BINARYBASE])
_AX_TEXT_TPL_SUBST([NAME_PACKAGE])
_AX_TEXT_TPL_SUBST([NAME_SERVICE])
_AX_TEXT_TPL_SUBST([NAME_SERVICE_VARNAME])
_AX_TEXT_TPL_SUBST([INIT_SYSTEM_SERVICE_PATH])

AC_MSG_CHECKING([whether to install compat %pgtest_* macros])
# This hack shouldn't be removed sooner than once the F27 postgresql is EOL,
Expand All @@ -235,10 +238,11 @@ AC_OUTPUT

AC_MSG_NOTICE([Configured the folowing way:

PostgreSQL version: $PGVERSION
PGDATADIR: $PGDATADIR
PostgreSQL service: $NAME_SERVICE
PostgreSQL package: $NAME_PACKAGE
PostgreSQL bin_pfx: $NAME_BINARYBASE
Init system: $INIT_SYSTEM
PostgreSQL version: $PGVERSION
PGDATADIR: $PGDATADIR
PostgreSQL service: $NAME_SERVICE
PostgreSQL package: $NAME_PACKAGE
PostgreSQL bin_pfx: $NAME_BINARYBASE
Init system: $INIT_SYSTEM
Init system services: $INIT_SYSTEM_SERVICE_PATH
])