Skip to content

Commit

Permalink
be selective about which files are modified when copied into a weewx-…
Browse files Browse the repository at this point in the history
…data area. eliminate antiquated init scripts. parameterize systemd units for precise pattern match. use consistent names for system integration scripts.
  • Loading branch information
matthewwall committed Dec 23, 2023
1 parent 5353b52 commit 33f18e8
Show file tree
Hide file tree
Showing 14 changed files with 258 additions and 849 deletions.
125 changes: 70 additions & 55 deletions src/weecfg/station_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -569,59 +569,73 @@ def copy_user(config_dict, user_root=None, dry_run=False):
def copy_util(config_path, config_dict, dry_run=False, force=False):
import weewxd
weewxd_path = weewxd.__file__
cfg_dir = os.path.dirname(config_path)
username = getpass.getuser()
groupname = grp.getgrgid(os.getgid()).gr_name
weewx_root = config_dict['WEEWX_ROOT']
# This is the set of substitutions to be performed. The key is a regular expression. If a
# match is found, the value will be substituted for the matched expression.
re_dict = {
# For systemd
r"^#User=.*": rf"User={username}",
# For systemd
r"^#Group=.*": rf"Group={groupname}",
# For systemd
r"^ExecStart=.*": rf"ExecStart={sys.executable} {weewxd_path} {config_path}",
# For init.d, redhat, bsd, suse
r"^WEEWX_BIN=.*": rf"WEEWX_BIN={sys.executable} {weewxd_path}",
# For init.d, redhat, bsd, suse
r"^WEEWX_CFG=.*": rf"WEEWX_CFG={config_path}",
# For init.d
r"^WEEWX_USER=.*": rf"WEEWX_USER={groupname}",
# For multi
r"^WEEWX_BINDIR=.*": rf"WEEWX_BINDIR={os.path.dirname(weewxd_path)}",
# For multi
r"^WEEWX_CFGDIR=.*": rf"WEEWX_CFGDIR={os.path.dirname(config_path)}",
# for macOS:
r"<string>/usr/bin/python3</string>": rf"<string>{sys.executable}<//string>",
# For macOS:
r"<string>/Users/Shared/weewx/src/weewxd.py</string>": rf"<string>{weewxd_path}</string>",
# For macOS:
r"<string>/Users/Shared/weewx/weewx.conf</string>": rf"<string>{config_path}</string>",
# For Apache
r"/home/weewx/public_html": rf"{os.path.join(weewx_root, 'public_html')}",
# For scripts
r"^UTIL_ROOT=.*": rf"UTIL_ROOT={os.path.join(weewx_root, 'util')}",
html_dir = os.path.join(weewx_root, 'public_html') # FIXME: get from conf
util_dir = os.path.join(weewx_root, 'util')
bin_dir = os.path.dirname(weewxd_path)

# This is the set of substitutions to be performed, with a different set
# for each type of files. The key is a regular expression. If a match is
# found, the value will be substituted for the matched expression. Beware
# that the labels for user, group, config directory, and other parameters
# are consistent throughout the utility files. Be sure to test the
# patterns by using them to grep all of the files in the util directory to
# see what actually matches.

re_patterns = {
'scripts': { # daemon install scripts
r"^UTIL_ROOT=.*": rf"UTIL_ROOT={util_dir}",
},
'systemd': { # systemd unit files
r"User=WEEWX_USER": rf"User={username}",
r"Group=WEEWX_GROUP": rf"Group={groupname}",
r"ExecStart=WEEWX_PYTHON WEEWXD": rf"ExecStart={sys.executable} {weewxd_path}",
r" WEEWX_CFGDIR/": rf" {cfg_dir}/",
},
'launchd': { # macos launchd files
r"<string>/usr/bin/python3</string>": rf"<string>{sys.executable}<//string>",
r"<string>/Users/Shared/weewx/src/weewxd.py</string>": rf"<string>{weewxd_path}</string>",
r"<string>/Users/Shared/weewx/weewx.conf</string>": rf"<string>{config_path}</string>",
},
'default': { # defaults file used by SysV init scripts
r"^WEEWX_PYTHON=.*": rf"WEEWX_PYTHON={sys.executable}",
r"^WEEWX_BINDIR=.*": rf"WEEWX_BINDIR={bin_dir}",
r"^WEEWX_CFGDIR=.*": rf"WEEWX_CFGDIR={cfg_dir}",
r"^WEEWX_USER=.*": rf"WEEWX_USER={username}",
r"^WEEWX_GROUP=.*": rf"WEEWX_GROUP={groupname}",
},
}
# Convert to a list of two-way tuples.
re_list = [(re.compile(key), re_dict[key]) for key in re_dict]

# Convert the patterns to a list of two-way tuples
for k in re_patterns:
re_patterns[k] = [(re.compile(key), re_patterns[k][key]) for key in re_patterns[k]],

def _patch_file(srcpath, dstpath):
"""Copy an individual file from srcpath to dstpath, while making substitutions
using the list of regular expressions re_list"""
with open(srcpath, 'r') as rd, open(dstpath, 'w') as wd:
for line in rd:
# Lines starting with "#&" are comment lines. Ignore them.
if line.startswith("#&"):
continue
# Go through all the regular expressions, substituting the value for the key
for key, value in re_list:
line = key.sub(value, line)
wd.write(line)
srcdir = os.path.dirname(srcpath)
if srcdir in re_patterns:
# Copy an individual file from srcpath to dstpath, while making
# substitutions using the list of regular expressions re_list
re_list = re_patterns[srcdir]
with open(srcpath, 'r') as rd, open(dstpath, 'w') as wd:
for line in rd:
# Lines starting with "#&" are comment lines. Ignore them.
if line.startswith("#&"):
continue
# Go through all the regular expressions, substituting the
# value for the key
for key, value in re_list:
line = key.sub(value, line)
wd.write(line)
else:
# Just copy the file
shutil.copyfile(srcpath, dstpath)

# Create a callable using the shutil.ignore_patterns factory function.
_ignore_function = shutil.ignore_patterns('*.pyc', '__pycache__', 'apache', 'default', 'i18n',
'init.d', 'logwatch', 'newsyslog.d',
'solaris', 'tmpfiles.d')
# The files/directories that match items in this list will *not* be copied.
_ignore_function = shutil.ignore_patterns('*.pyc', '__pycache__')

util_dir = os.path.join(weewx_root, 'util')
if os.path.isdir(util_dir):
Expand All @@ -636,18 +650,18 @@ def _patch_file(srcpath, dstpath):
with weeutil.weeutil.get_resource_path('weewx_data', 'util') as util_resources:
print(f"Copying utility files into {util_dir}")
if not dry_run:
# Copy the tree rooted in 'util_resources' to 'dstdir', while ignoring files given
# by _ignore_function. While copying, use the function _patch_file() to massage
# the files.
# Copy the tree rooted in 'util_resources' to 'dstdir', while
# ignoring files given by _ignore_function. While copying, use the
# function _patch_file() to massage the files.
shutil.copytree(util_resources, util_dir,
ignore=_ignore_function,
copy_function=_patch_file)
ignore=_ignore_function, copy_function=_patch_file)

scripts_dir = os.path.join(weewx_root, 'scripts')

# The 'scripts' subdirectory is a little different. We don't delete it first, because it's a
# comman name and a user might have put things there. Instead, just copy our files into it.
# First, make sure the subdirectory exists:
# The 'scripts' subdirectory is a little different. We do not delete it
# first, because it's a comman name and a user might have put things there.
# Instead, just copy our files into it. First, make sure the subdirectory
# exists:
os.makedirs(scripts_dir, exist_ok=True)
# Then do the copying.
with weeutil.weeutil.get_resource_path('weewx_data', 'scripts') as scripts_resources:
Expand All @@ -658,8 +672,9 @@ def _patch_file(srcpath, dstpath):
abs_dst = os.path.join(scripts_dir, file)
_patch_file(abs_src, abs_dst)
status = os.stat(abs_dst)
# Because these files have been tailored to a particular user, they hould only
# be executable by that user. So, use S_IXUSR (instead of S_IXOTH):
# Because these files have been tailored to a particular user,
# they hould only be executable by that user. So, use S_IXUSR
# (instead of S_IXOTH):
os.chmod(abs_dst, status.st_mode | stat.S_IXUSR)

return util_dir
Expand Down
35 changes: 27 additions & 8 deletions src/weewx_data/scripts/setup-daemon.macos
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
#!/bin/sh
#
# Copy configurations that integrate WeeWX into a macOS system.
#
# Install files that integrate WeeWX into a macOS system.
# This script must be run as a privileged user.
#
set -e
Expand All @@ -13,9 +12,31 @@ if [ "$(id -u)" != "0" ]; then
exit 1
fi

if [ ! -d /Library/LaunchDaemons ]; then
echo "Apparently this system does not use launchd"
exit 1
fi

ts=`date +"%Y%m%d%H%M%S"`

copy_file() {
src=$1
dst=$2
if [ -f "$dst" ]; then
mv ${dst} ${dst}.${ts}
fi
cp $src $dst
}

remove_file() {
dst=$1
if [ -f "$dst" ]; then
rm $dst
fi
}

do_install() {
echo "This script sets up the files necessary to run WeeWX at system startup."
echo "On some systems, it can be slow to run. Please be patient."
echo "Set up the files necessary to run WeeWX at system startup."

if [ ! -d $UTIL_ROOT ]; then
echo "Cannot find utility files at location '$UTIL_ROOT'"
Expand All @@ -24,7 +45,7 @@ do_install() {

echo "Copying files from $UTIL_ROOT..."
echo " plist"
cp $UTIL_ROOT/launchd/com.weewx.weewxd.plist /Library/LaunchDaemons
copy_file $UTIL_ROOT/launchd/com.weewx.weewxd.plist /Library/LaunchDaemons

echo "You can now start weewx with the following command:"
echo " '\033[1msudo launchctl load /Library/LaunchDaemons/com.weewx.weewxd.plist\033[0m'"
Expand All @@ -35,9 +56,7 @@ do_uninstall() {
launchctl unload /Library/LaunchDaemons/com.weewx.weewxd.plist
echo "Removing files..."
echo " plist"
if [ -f /Library/LaunchDaemons/com.weewx.weewxd.plist ]; then
rm /Library/LaunchDaemons/com.weewx.weewxd.plist
fi
remove_file /Library/LaunchDaemons/com.weewx.weewxd.plist
}


Expand Down
69 changes: 40 additions & 29 deletions src/weewx_data/scripts/setup-daemon.systemd
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
#!/bin/sh
#
# Copy configuration files that integrate WeeWX into a Linux system that uses
# systemd. These include udev rules for known devices, and the service unit
# files to facilitate starting/stopping WeeWX.
#
# Install files that integrate WeeWX into a Linux system that uses systemd.
# This script must be run using sudo, or as root.
#
set -e
Expand All @@ -15,9 +12,32 @@ if [ "$(id -u)" != "0" ]; then
exit 1
fi

if [ ! -d /etc/systemd/system ]; then
echo "Apparently this system does not use systemd"
exit 1
fi

ts=`date +"%Y%m%d%H%M%S"`

copy_file() {
src=$1
dst=$2
if [ -f "$dst" ]; then
mv ${dst} ${dst}.${ts}
fi
cp $src $dst
}

remove_file() {
dst=$1
if [ -f "$dst" ]; then
rm $dst
fi
}

do_install() {
echo "This script sets up the files necessary to run WeeWX at system startup."
echo "On some systems, it can be slow to run. Please be patient."
echo "Set up the files necessary to run WeeWX at system startup."
echo "On some systems, this may take awhile. Please be patient."

if [ ! -d $UTIL_ROOT ]; then
echo "Cannot find utility files at location '$UTIL_ROOT'"
Expand All @@ -27,23 +47,20 @@ do_install() {
echo "Copying files from $UTIL_ROOT..."
if [ -d /etc/udev/rules.d ]; then
echo " udev rules"
cp $UTIL_ROOT/udev/rules.d/weewx.rules /etc/udev/rules.d/60-weewx.rules
fi
if [ -d /etc/systemd/system ]; then
echo " systemd unit"
cp $UTIL_ROOT/systemd/weewx.service /etc/systemd/system
cp $UTIL_ROOT/systemd/weewx@.service /etc/systemd/system
copy_file $UTIL_ROOT/udev/rules.d/weewx.rules /etc/udev/rules.d/60-weewx.rules
echo " If you are using a device that is connected to the computer by USB or"
echo " serial port, unplug the device then plug it back in again to ensure that"
echo " permissions are applied correctly."
fi

echo " systemd unit"
copy_file $UTIL_ROOT/systemd/weewx.service /etc/systemd/system/weewx.service
copy_file $UTIL_ROOT/systemd/weewx@.service /etc/systemd/system/weewx@.service

echo "Reloading systemd..."
systemctl daemon-reload
echo "Enabling weewx..."
systemctl enable weewx

echo "If you are using a device that is connected to the computer by USB or"
echo "serial port, unplug the device then plug it back in again to ensure that"
echo "permissions are applied correctly."
echo ""
echo "You can start weewx with the following command:"
echo " '\033[1msudo systemctl start weewx\033[0m'"
}
Expand All @@ -54,18 +71,12 @@ do_uninstall() {
echo "Disabling weewx..."
systemctl disable weewx
echo "Removing files..."
if [ -f /etc/systemd/system/weewx.service ]; then
echo " systemd unit"
rm /etc/systemd/system/weewx.service
fi
if [ -f /etc/systemd/system/weewx@.service ]; then
echo " systemd unit template"
rm /etc/systemd/system/weewx@.service
fi
if [ -f /etc/udev/rules.d/60-weewx.rules ]; then
echo " udev rules"
rm /etc/udev/rules.d/60-weewx.rules
fi
echo " systemd unit"
remove_file /etc/systemd/system/weewx.service
echo " systemd unit template"
remove_file /etc/systemd/system/weewx@.service
echo " udev rules"
remove_file /etc/udev/rules.d/60-weewx.rules
}

ACTION=$1
Expand Down

0 comments on commit 33f18e8

Please sign in to comment.