#!/bin/bash
#------------------------------------------------------------------------------
# gen_p4dtg_env.sh
#
# To see documentation for this script, run:
# gen_p4dtg_env.sh -man
#------------------------------------------------------------------------------
set -u
# Counters and message helpers.
declare -i ErrorCount=0
declare -i WarningCount=0
function msg () { echo -e "$*"; }
function errmsg () { msg "\\nError: ${1:-Unknown Error}\\n"; ErrorCount+=1; }
function warnmsg () { msg "\\nWarning: ${1:-Unknown Warning}\\n"; WarningCount+=1; }
function bail () { errmsg "${1:-Unknown Error}"; exit "$ErrorCount"; }
# Standard identity vars.
declare ThisScript="${0##*/}"
declare Args="$*"
declare CmdLine="$ThisScript $Args"
declare Version="1.1.2"
declare ThisUser=
declare ThisHost=${HOSTNAME%%.*}
ThisUser="$(id -un 2>/dev/null || echo unknown)"
msg "Starting $ThisScript v$Version as $ThisUser@$ThisHost on $(date) with \\n$CmdLine"
usage() {
# usage <style> [usageErrorMessage]
# style: "short"|"man"
declare style="${1:-short}"
declare usageErrorMessage="${2:-}"
[[ -n "$usageErrorMessage" ]] && errmsg "$usageErrorMessage"
msg "Usage:"
msg " $ThisScript -c <P4DTGConfigName> [-i <SDPInstance>] [-u <P4USER>] [-f]"
msg " $ThisScript -verify [-i <SDPInstance>] [-e <EnvFile>]"
msg " $ThisScript -V|-version|--version"
msg " $ThisScript -h|-man"
msg ""
if [[ "$style" == "man" ]]; then
msg "DESCRIPTION"
msg " Generates or verifies the systemd EnvironmentFile for a P4DTG instance."
msg ""
msg "MODES"
msg " Generate mode:"
msg " -c <P4DTGConfigName> is required."
msg " Writes: \$P4CCFG/p4dtg_<instance>.env"
msg ""
msg " Verify mode:"
msg " -verify validates an existing env file."
msg " By default it validates: \$P4CCFG/p4dtg_<instance>.env"
msg " You can override with: -e <EnvFile>"
msg ""
msg "OPTIONS"
msg " -i <SDPInstance>"
msg " Optional. If omitted, uses \$SDP_INSTANCE; otherwise error."
msg ""
msg " -c <P4DTGConfigName>"
msg " Required for generate mode. Sets P4DTG_CFG."
msg ""
msg " -u <P4USER>"
msg " Optional. Defaults to 'p4dtg'. Used in generated env file as P4USER."
msg ""
msg " -f"
msg " Force overwrite in generate mode."
msg " Existing env file moved aside as .bak.YYYY-MM-DD-HHMMSS"
msg ""
msg " -verify"
msg " Verify mode."
msg ""
msg " -e <EnvFile>"
msg " Optional with -verify. Verify this explicit env file path."
msg ""
msg " -V|-version|--version"
msg " Display version and exit."
msg ""
msg " -h|-man"
msg " Display help. -man shows extended help."
msg ""
msg "NOTES"
msg " - Sources SDP environment with: /p4/common/bin/p4_vars <instance>"
msg " - P4PORT selection for generated env file:"
msg " If /p4/<inst>/bin/p4broker_<inst>_init exists and is executable -> P4PORT=\$P4BROKERPORT"
msg " else -> P4PORT=\$P4PORT"
msg " - Includes P4CHARSET and P4COMMANDCHARSET only if defined and non-empty."
msg " - P4DTG_ROOT is currently hard-coded to /p4/common/dtg."
msg " - HOME is set to /home/perforce."
msg ""
fi
exit 2
}
# ----------------------------
# Defaults / inputs
# ----------------------------
declare SDPInstance="${SDP_INSTANCE:-}"
declare P4DTG_CFG=""
declare P4User="p4dtg"
declare Force=0
declare DoVerify=0
declare VerifyEnvFile=""
# ----------------------------
# Command Line Processing.
# ----------------------------
declare shiftArgs=0
while [[ $# -gt 0 ]]; do
shiftArgs=0
case "${1}" in
(-h) usage "short" ;;
(-man) usage "man" ;;
(-V|-version|--version)
msg "$ThisScript v$Version"
exit 0
;;
(-i) SDPInstance="${2:-}"; shiftArgs=2 ;;
(-c) P4DTG_CFG="${2:-}"; shiftArgs=2 ;;
(-u) P4User="${2:-}"; shiftArgs=2 ;;
(-f) Force=1; shiftArgs=1 ;;
(-verify) DoVerify=1; shiftArgs=1 ;;
(-e) VerifyEnvFile="${2:-}"; shiftArgs=2 ;;
(-*)
usage "short" "Unknown option: ${1}"
;;
(*)
usage "short" "Unexpected parameter: ${1}"
;;
esac
shift "$shiftArgs"
done
# Validate instance presence
[[ -n "${SDPInstance}" ]] || usage "short" "SDP instance not specified. Use -i or set SDP_INSTANCE."
# Conservative sanity for instance name
if [[ ! "$SDPInstance" =~ ^[A-Za-z0-9][A-Za-z0-9_-]*$ ]]; then
bail "Invalid SDP instance name: '$SDPInstance'"
fi
# ----------------------------
# Source SDP environment
# ----------------------------
declare P4Vars="/p4/common/bin/p4_vars"
[[ -r "$P4Vars" ]] || bail "Missing or unreadable: $P4Vars"
# shellcheck disable=SC1090
source "$P4Vars" "$SDPInstance" || bail "Failed to source SDP environment with: $P4Vars $SDPInstance"
[[ -n "${P4CCFG:-}" ]] || bail "P4CCFG is not set after sourcing p4_vars for instance '$SDPInstance'"
# Compute default env file path now that P4CCFG is known.
declare DefaultEnvFile="${P4CCFG}/p4dtg_${SDPInstance}.env"
# ----------------------------
# Verify mode
# ----------------------------
verify_env_file() {
declare envFile="${1:-}"
[[ -n "$envFile" ]] || bail "verify_env_file called with empty path."
[[ -r "$envFile" ]] || bail "Env file not found or not readable: $envFile"
# Basic format check: KEY=VALUE lines; ignore comments/blank.
# Required keys:
declare -a requiredKeys=(P4DTG_CFG P4DTG_ROOT HOME P4PORT P4USER)
declare k=""
for k in "${requiredKeys[@]}"; do
if ! grep -Eq "^[[:space:]]*${k}=" "$envFile"; then
bail "Env file missing required key: $k"
fi
# Ensure non-empty value (KEY= followed by at least one char)
if grep -Eq "^[[:space:]]*${k}=[[:space:]]*$" "$envFile"; then
bail "Env file has empty value for key: $k"
fi
done
# Optional keys should not be present with empty values (if present)
declare -a optionalKeys=(P4CHARSET P4COMMANDCHARSET P4TICKETS P4TRUST)
for k in "${optionalKeys[@]}"; do
if grep -Eq "^[[:space:]]*${k}=[[:space:]]*$" "$envFile"; then
bail "Env file has empty value for optional key (remove it or set value): $k"
fi
done
# Validate that DTG_ROOT is the expected value (for now, hard-coded requirement).
if ! grep -Eq '^[[:space:]]*P4DTG_ROOT=/p4/common/dtg[[:space:]]*$' "$envFile"; then
warnmsg "P4DTG_ROOT is not '/p4/common/dtg' in $envFile (verify whether this is intended)."
fi
# Validate broker-port logic consistency (warn only, since admins may override on purpose).
# Determine expected DTG_P4PORT using the same rule as generation.
[[ -n "${P4PORT:-}" ]] || bail "P4PORT is not set after sourcing p4_vars for instance '$SDPInstance'"
declare BrokerInit="/p4/${SDPInstance}/bin/p4broker_${SDPInstance}_init"
declare ExpectedP4PORT="$P4PORT"
if [[ -x "$BrokerInit" && -n "${P4BROKERPORT:-}" ]]; then
ExpectedP4PORT="$P4BROKERPORT"
fi
declare ActualP4PORT
ActualP4PORT="$(grep -E '^[[:space:]]*P4PORT=' "$envFile" | head -1 | sed -E 's/^[[:space:]]*P4PORT=//')"
if [[ -n "$ExpectedP4PORT" && -n "$ActualP4PORT" && "$ExpectedP4PORT" != "$ActualP4PORT" ]]; then
warnmsg "P4PORT in env file ('$ActualP4PORT') does not match expected ('$ExpectedP4PORT') for instance '$SDPInstance'."
fi
msg "Verified OK: $envFile"
exit "$ErrorCount"
}
if [[ "$DoVerify" -eq 1 ]]; then
declare envToVerify="$DefaultEnvFile"
if [[ -n "$VerifyEnvFile" ]]; then
envToVerify="$VerifyEnvFile"
fi
verify_env_file "$envToVerify"
fi
# ----------------------------
# Generate mode validations
# ----------------------------
[[ -n "${P4DTG_CFG}" ]] || usage "short" "Missing required -c <P4DTGConfigName> for generate mode."
# Expect key vars from sourced env
[[ -n "${P4PORT:-}" ]] || bail "P4PORT is not set after sourcing p4_vars for instance '$SDPInstance'"
# ----------------------------
# Determine DTG P4PORT for generated env file
# ----------------------------
declare BrokerInit="/p4/${SDPInstance}/bin/p4broker_${SDPInstance}_init"
declare DTG_P4PORT="$P4PORT"
if [[ -x "$BrokerInit" ]]; then
if [[ -n "${P4BROKERPORT:-}" ]]; then
DTG_P4PORT="$P4BROKERPORT"
else
warnmsg "Broker init exists ($BrokerInit) but P4BROKERPORT is not set; falling back to P4PORT='$P4PORT'"
fi
fi
# ----------------------------
# Output file paths
# ----------------------------
declare OutDir="$P4CCFG"
declare OutFile="$DefaultEnvFile"
declare TmpFile="${OutFile}.tmp.$$"
[[ -d "$OutDir" ]] || bail "Output directory not found: $OutDir"
[[ -w "$OutDir" ]] || bail "Output directory not writable: $OutDir"
# Safety: don't overwrite unless -f
if [[ -e "$OutFile" ]]; then
if [[ "$Force" -eq 1 ]]; then
declare Back=
Back="${OutFile}.bak.$(date +'%Y-%m-%d-%H%M%S')"
mv -f "$OutFile" "$Back" || bail "Failed to move existing env file aside to: $Back"
msg "Moved existing env file aside to: $Back"
else
bail "Refusing to overwrite existing env file: $OutFile (use -f to force)"
fi
fi
# Restrictive permissions
umask 077
# ----------------------------
# Generate env file
# ----------------------------
{
echo "# Generated by $ThisScript v$Version on $(date -u '+%Y-%m-%d %H:%M:%S UTC')"
echo "# Instance: $SDPInstance"
echo ""
echo "P4DTG_CFG=$P4DTG_CFG"
echo "P4DTG_ROOT=/p4/common/dtg"
echo "HOME=/home/perforce"
echo ""
echo "P4PORT=$DTG_P4PORT"
echo "P4USER=$P4User"
# Include only if defined and non-empty
if [[ -n "${P4CHARSET:-}" ]]; then
echo "P4CHARSET=$P4CHARSET"
fi
if [[ -n "${P4COMMANDCHARSET:-}" ]]; then
echo "P4COMMANDCHARSET=$P4COMMANDCHARSET"
fi
# Pass through if available (optional)
if [[ -n "${P4TICKETS:-}" ]]; then
echo "P4TICKETS=$P4TICKETS"
fi
if [[ -n "${P4TRUST:-}" ]]; then
echo "P4TRUST=$P4TRUST"
fi
} > "$TmpFile" || bail "Failed writing temp env file: $TmpFile"
mv -f "$TmpFile" "$OutFile" || bail "Failed moving $TmpFile to $OutFile"
chmod 600 "$OutFile" 2>/dev/null || true
msg "Wrote: $OutFile"
exit "$ErrorCount"
| # | Change | User | Description | Committed | |
|---|---|---|---|---|---|
| #1 | 32482 | C. Thomas Tyler |
Merge down from //p4-sdp/dev -> //p4-sdp/dev_rebrand. This was initiated with 'p4 merge' (no options). The 'p4 resolve -as', 'p4 resolve -am' and several interactive resolves were done. |
||
| //p4-sdp/dev/Server/Unix/p4/common/bin/gen_p4dtg_env.sh | |||||
| #1 | 32480 | C. Thomas Tyler |
Routine merge for SDP from Classic to Streams, done with: p4 merge -b SDP_Classic_to_Streams p4 resolve -as The automatic-safe resolve handled all files; neither '-am' nor interative resolves were needed. |
||
| //guest/perforce_software/sdp/dev/Server/Unix/p4/common/bin/gen_p4dtg_env.sh | |||||
| #1 | 32402 | C. Thomas Tyler |
Fixed so the p4dtg_N (P4DTG) service can be managed with systmectl, e.g. sudo systemctl start p4dtg_1 sudo systemctl status p4dtg_1 sudo systemctl stop p4dtg_1 Also added support for a "force_start" option, similar to that being added for p4d (per SDP-837). This change includes: * Modifiedcation to the temmplate for the p4dtg_N_init script. * Addition of new template for the systemd p4dtg_N.service file. * Added a new script to generate a systemctl-compatible environment file from the standard SDP shell environment mechanism. See: SDP-552. #review-32403 |
||