HEX
Server: nginx/1.18.0
System: Linux hqnl0246134.online-vm.com 5.4.0-135-generic #152-Ubuntu SMP Wed Nov 23 20:19:22 UTC 2022 x86_64
User: www-data (33)
PHP: 7.4.33
Disabled: phpinfo,disk_free_space,disk_total_space,diskfreespace,dl,exec,opcache_get_configuration,opcache_get_status,passthru,pclose,pcntl_alarm,pcntl_exec,pcntl_fork,pcntl_get_last_error,pcntl_getpriority,pcntl_setpriority,pcntl_signal,pcntl_signal_dispatch,pcntl_sigprocmask,pcntl_sigtimedwait,pcntl_sigwaitinfo,pcntl_strerror,pcntl_waitpid,pcntl_wait,pcntl_wexitstatus,pcntl_wifcontinued,pcntl_wifexited,pcntl_wifsignaled,pcntl_wifstopped,pcntl_wstopsig,pcntl_wtermsig,popen,posix_getpwuid,posix_kill,posix_mkfifo,posix_setpgid,posix_setsid,posix_setuid,posix_uname,proc_close,proc_get_status,proc_nice,proc_terminate,shell_exec,show_source,system,exec,passthru,shell_exec,system,popen,curl_exec,curl_multi_exec,parse_ini_file,show_source
Upload Files
File: /var/www/secured/artro-patch.com.ua/php-chroot-bind
#!/bin/bash
_CHROOTS_CMD="ls -1d /var/www/secured/*/"
_SYSTEMD_UNIT_DIR="/etc/systemd/system"
_BIND="\
	/usr/share/zoneinfo \
	/dev/urandom \
	/dev/zero \
	/dev/null \
	/etc/resolv.conf \
	/lib/x86_64-linux-gnu/libnss_dns.so.2 \
	/usr/share/ca-certificates \
	/etc/ssl/certs"

# File with additional binds for specific chroots. Relative to the chroot.
_BIND_LOCAL="../bind.conf"


is_bound() {
	mount | grep " on $1 type " > /dev/null && return 0 || return 1
}


get_binds() {
	local chroot="$1"
	echo $_BIND
	cd "$chroot"
	[ -f "$_BIND_LOCAL" ] && cat "$_BIND_LOCAL"
}

delete_path() {
	local chroot="$1"
	local path="$2"
	local lastPath=""
	local cmd="echo \" (Not deleted, use -do)\""
	while [ "$path" != "/" ]; do lastPath="$path"; path=`dirname $path`; done;
	$_OPT_DO && cmd="rm -rf \"${chroot}${lastPath}\" && echo \" (deleted)\""
	[ -e "${chroot}${lastPath}" ] && echo -en "\tRemove: ${chroot}${lastPath}" && eval "$cmd" && return 0
	return 1
}

create_systemd_units() {

	local chroot=""
	local eChroot=""
	local bind=""
	local eBind=""
	local mountpoint=""

	[ ! -f "${_SYSTEMD_UNIT_DIR}/php-chroots.target" ] && \
	cat <<- END > "${_SYSTEMD_UNIT_DIR}/php-chroots.target" && \
	echo -e "Created ${_SYSTEMD_UNIT_DIR}/php-chroots.target"
	# PHP-FPM-CHROOT-BIND
	[Install]
	WantedBy=php7.0-fpm.service

	[Unit]
	Description=Bind all binds for all PHP-FPM chroots
	Before=php7.0-fpm.service
	END

	$_CHROOTS_CMD | while read chroot; do
		eChroot="`systemd-escape -p \"${chroot}\"`"

		[ ! -f "${_SYSTEMD_UNIT_DIR}/php-chroot-${eChroot}.target" ] && \
		cat <<- END > "${_SYSTEMD_UNIT_DIR}/php-chroot-${eChroot}.target" && \
		echo -e "Created ${_SYSTEMD_UNIT_DIR}/php-chroot-${eChroot}.target"
		# PHP-FPM-CHROOT-BIND
		[Unit]
		Description=Bind all binds for PHP-FPM chroot ${chroot}
		END

		for bind in `get_binds "${chroot}"`; do
			eBind="`systemd-escape -p \"${bind}\"`"
			mountpoint="`systemd-escape -p \"${chroot}${bind}\"`"

			[ ! -f "${_SYSTEMD_UNIT_DIR}/${mountpoint}.mount" ] && \
			cat <<- END > "${_SYSTEMD_UNIT_DIR}/${mountpoint}.mount" && \
			echo -e "Created ${_SYSTEMD_UNIT_DIR}/${mountpoint}.mount"
			# PHP-FPM-CHROOT-BIND
			[Unit]
			Description=Bind ${bind} for PHP-FPM chroot ${chroot}
			Requires=php-chroot-create-mountpoint-file-${eBind}@${eChroot}.service
			Requires=php-chroot-create-mountpoint-dir-${eBind}@${eChroot}.service
			BindsTo=php-chroot-${eChroot}.target

			[Mount]
			What=${bind}
			Where=${chroot}${bind}
			Type=none
			Options=bind
			END

			[ ! -f "${_SYSTEMD_UNIT_DIR}/php-chroot-create-mountpoint-file-${eBind}@.service" ] && \
			cat <<- END > "${_SYSTEMD_UNIT_DIR}/php-chroot-create-mountpoint-file-${eBind}@.service" && \
			echo -e "Created ${_SYSTEMD_UNIT_DIR}/php-chroot-create-mountpoint-file-${eBind}@.service"
			# PHP-FPM-CHROOT-BIND
			[Unit]
			Description=Create mountpoint (file) for ${bind} in PHP-FPM Chroot
			Before=%i-${eBind}.mount
			ConditionPathExists=!/%I${bind}
			ConditionPathExists=${bind}
			ConditionPathIsDirectory=!${bind}

			[Service]
			Type=oneshot
			ExecStart=/bin/mkdir -p "/%I${bind}" ; /bin/rm -r "/%I${bind}" ; /usr/bin/touch "/%I${bind}"
			END

			[ ! -f "${_SYSTEMD_UNIT_DIR}/php-chroot-create-mountpoint-dir-${eBind}@.service" ] && \
			cat <<- END > "${_SYSTEMD_UNIT_DIR}/php-chroot-create-mountpoint-dir-${eBind}@.service" && \
			echo -e "Created ${_SYSTEMD_UNIT_DIR}/php-chroot-create-mountpoint-dir-${eBind}@.service"
			# PHP-FPM-CHROOT-BIND
			[Unit]
			Description=Create mountpoint (dir) for ${bind} in PHP-FPM Chroot
			Before=%i-${eBind}.mount
			ConditionPathExists=!/%I${bind}
			ConditionPathExists=${bind}
			ConditionPathIsDirectory=${bind}

			[Service]
			Type=oneshot
			ExecStart=/bin/mkdir -p "/%I${bind}"
			END

			echo "Requires=${mountpoint}.mount" >> "${_SYSTEMD_UNIT_DIR}/php-chroot-${eChroot}.target"
		done
		echo "BindsTo=php-chroots.target" >> "${_SYSTEMD_UNIT_DIR}/php-chroot-${eChroot}.target"
		echo "Wants=php-chroot-${eChroot}.target" >> "${_SYSTEMD_UNIT_DIR}/php-chroots.target"
	done
	return 0
}

list_systemd_units() {
	local unit=""
	ls -1b "${_SYSTEMD_UNIT_DIR}/"* 2> /dev/null | while read unit; do
		[ -f "$unit" ] && head -n1 "${unit}" | \
		grep -x "# PHP-FPM-CHROOT-BIND" > /dev/null && echo "${unit}"
	done
	return 0
}

delete_systemd_units() {
	ls -1b "${_SYSTEMD_UNIT_DIR}/"* 2> /dev/null | while read unit; do
		[ -f "$unit" ] && head -n1 "${unit}" | \
		grep -x "# PHP-FPM-CHROOT-BIND" > /dev/null && \
		echo -n "${unit}" && if $_OPT_DO; then
			rm "${unit}" && echo " (deleted)"
		else
			echo " (not deleted, use -do)"
		fi
	done
	return 0
}

# Parse commandline
_OPT_CLEAN=false
_OPT_CREATE=false
_OPT_LIST=false
_OPT_DO=false
_OPT_UPDATE=false
case "$1" in
	"status") _OPT_ACTION="status";;
	"bind"  ) _OPT_ACTION="bind";;

	"unbind")
		_OPT_ACTION="unbind"
		[ "$2" = "clean" ] && _OPT_CLEAN=true
		[ "$3" = "-do" ] && _OPT_DO=true
		[ -n "$2" ] && ! $_OPT_CLEAN && _OPT_ACTION="help"
		[ -n "$3" ] && ! $_OPT_DO && _OPT_ACTION="help"
		;;

	"systemd")
		_OPT_ACTION="systemd"
		[ "$2" = "clean" ] && _OPT_CLEAN=true
		[ "$2" = "create" ] && _OPT_CREATE=true
		[ "$2" = "list" ] && _OPT_LIST=true
		[ "$2" = "update" ] && _OPT_UPDATE=true
		$_OPT_CLEAN || $_OPT_CREATE || $_OPT_LIST || $_OPT_UPDATE || _OPT_ACTION="help"
		[ "$3" = "-do" ] && _OPT_DO=true
		[ -n "$3" ] && ! $_OPT_DO && _OPT_ACTION="help"
		;;

	*) _OPT_ACTION="help";;
esac

# Print help
[ "$_OPT_ACTION" = "help" ] && cat <<EOF && exit 1
Usage: $0 <command> [<subcommand> [-do]]

	<command> can be one of

	status:

		Show if pathes defined in \$_BIND are mounted (green)
		or not (red)

	bind: 

		Bind any path defined in \$_BIND to any chroot
		given by \$_CHROOTS_CMD if it is not bound already.

	unbind [clean [-do]]:

		Unmount all binds defined in \$_BIND mounted to chroots.

		If "clean" is given, the mountpoints created for binding
		will be deleted. If -do is omitted it will only print what
		would be deleted. Use with -do to actually delete.

	systemd create:

		Create systemd unit files in \$_SYSTEMD_UNIT_DIR to
		setup binds automatically on boot.

	systemd list:

		List systemd unit files in \$_SYSTEMD_UNIT_DIR

	systemd clean [-do]:

		Remove all files from \$_SYSTEMD_UNIT_DIR generated by
		this script. Files are determined by starting with

		 # PHP-FPM-CHROOT bind

		Without -do it is only shown what files would be deleted.
		Use with -do to actually delete.

	systemd update:

		Same as

		$0 systemd clean -do && $0 systemd create

		Can be used to keep systemd configuration for binds
		in sync with available chroots.
EOF


# List systemd unit files
[ "$_OPT_ACTION" = "systemd" ] && $_OPT_LIST && list_systemd_units && exit

# Set up systemd unit files
[ "$_OPT_ACTION" = "systemd" ] && $_OPT_CREATE && create_systemd_units && exit

# Clean up systemd unit files
[ "$_OPT_ACTION" = "systemd" ] && $_OPT_CLEAN && delete_systemd_units && exit

# Update systemd unit files
[ "$_OPT_ACTION" = "systemd" ] && $_OPT_UPDATE && $0 systemd clean -do && $0 systemd create && systemctl daemon-reload && exit

# Do operation with chroots
$_CHROOTS_CMD | while read chroot; do
	echo "Chroot: $chroot"
	for bind in `get_binds "${chroot}"`; do
		
		mountpoint="${chroot}${bind}"

		# List binds
		if [ "$_OPT_ACTION" = "status" ]; then
			is_bound "$mountpoint" && echo -en "\t\033[32m+" || echo -en "\t\033[31m-"
			echo -e "\033[0m ${bind}"
			continue
		fi

		# Bind if not bound
		if [ "$_OPT_ACTION" = "bind" ] && ! is_bound "${mountpoint}"; then
			# Create mountpoint (could be directory or file)
			[ -d "${bind}" ] && mkdir -p "${mountpoint}" || mkdir -p "${chroot}`dirname ${bind}`" && touch "${mountpoint}"
			# Mount bind read-only
			echo -en "\t  "  && mount -v -o "bind,ro" "${bind}" "${mountpoint}"
			continue
		fi

		# Unbind if bound
		[ "$_OPT_ACTION" = "unbind" ] && is_bound "${mountpoint}" && echo -en "\t" && umount -v "${mountpoint}"

	done;
	# Clean up directories and files created as mountpoint
	[ "$_OPT_ACTION" = "unbind" ] && $_OPT_CLEAN && for bind in `get_binds "${chroot}"`; do delete_path "${chroot}" "${bind}"; done;
done;