Skip to content

Commit

Permalink
feat: Warn if cron is not running
Browse files Browse the repository at this point in the history
Warn if no Cron instance is running.

The list of processes running on the system are grepped case-insensitive for the string `cron`. That would catch cronie, fcron and similar cron derivatives. This will help especially on Arch-based system often installing cron but not enabling it.

Additionally modified TravisCI to use the oldest supported Python version (3.8) only. This will save credits on TravisCI. Also upgraded Ubuntu from Focal (20.04 LTS) to Jammy (22.04 LTS).

Fix a minor bug introduced via #1747.

Fix #1741 
Fix #1765
  • Loading branch information
buhtz authored Jun 15, 2024
1 parent 22a050d commit 6132d72
Show file tree
Hide file tree
Showing 7 changed files with 62 additions and 21 deletions.
10 changes: 7 additions & 3 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@

os: linux

# ensures that we have UUID filesystem mounts for proper testing
dist: focal
# Support End of "Focal" (20.04 LTS) is April 2025
# dist: focal
# Support End of "Jammy" (22.04 LTS) is April 2027
dist: jammy

language: python

Expand Down Expand Up @@ -33,15 +35,17 @@ before_install:
- sudo apt-key del 90CFB1F5
- sudo apt-get -qq update
# install screen, and util-linux (provides flock) for test_sshtools
- sudo apt-get install -y sshfs screen util-linux
- sudo apt-get install -y sshfs screen util-linux libdbus-1-dev

jobs:
exclude:
- python: "3.9"
- python: "3.10"
- python: "3.11"
- python: "3.12"

install:
- pip install -U pip
- pip install pylint coveralls pyfakefs keyring
- pip install pyqt6 dbus-python
# add ssh public / private key pair to ensure user can start ssh session to localhost for tests
Expand Down
1 change: 1 addition & 0 deletions CHANGES
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
Back In Time

Version 1.4.4-dev (development of upcoming release)
* Feature: Warn if Cron is not running (#1747)
* Build: Activate PyLint error C0303 (trailing-whitespaces)
* Build: Activate PyLint error W0311 (bad-indentation)
* Build: Activate PyLint error E0100 (init-is-generator), E0101 (return-in-init), E0102 (function-redefined), E0103 (not-in-loop), E0106 (return-arg-in-generator)
Expand Down
25 changes: 13 additions & 12 deletions common/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -1627,6 +1627,7 @@ def setupCron(self):
# Add a new entry to existing crontab content based on the current
# snapshot profile and its schedule settings.
crontab_lines = schedule.append_bit_to_crontab(
crontab_lines,
self.profiles_cron_lines())

# Save Udev rules
Expand All @@ -1643,20 +1644,22 @@ def setupCron(self):
if crontab_lines == org_crontab_lines:
return True

# TODO (buhtz): Again a crontab check. Refactore somehow.
if not tools.checkCommand('crontab'):
logger.error('crontab not found.', self)
self.notifyError(_(
"Can't find crontab.\n"
"Are you sure cron is installed?\n"
"If not you should disable all automatic backups."))

return False

if schedule.write_crontab(crontab_lines) == False:
logger.error('Failed to write new crontab.')
self.notifyError(_('Failed to write new crontab.'))
return False

if not schedule.is_cron_running():
logger.error(
'Cron is not running despite the crontab command being '
'available. Scheduled backup jobs will not run.')
self.notifyError(_(
'Cron is not running despite the crontab command being '
'available. Scheduled backup jobs will not run. '
'Cron might be installed but not enabled. Try the command '
'"systemctl enable cron" or consulte the support channels of '
'your GNU Linux distribution.'))

return True

def profiles_cron_lines(self):
Expand All @@ -1666,14 +1669,12 @@ def profiles_cron_lines(self):
list: The list of crontab lines.
"""
profile_ids = self.profiles()
print(f'{profile_ids=}') # DEBUG

# For each profile: cronline and the command (backintime)
cron_lines = [
self._cron_line(pid).replace('{cmd}', self._cron_cmd(pid))
for pid in profile_ids
]
print(f'{cron_lines=}') # DEBUG

# Remove empty lines (profiles not scheduled)
cron_lines = list(filter(None, cron_lines))
Expand Down
6 changes: 4 additions & 2 deletions common/doc-dev/BiT_release_process.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ using a "feature" branch and sending a pull request asking for a review.

- Developers agreed on the new version number.
- Most-recent translations were merged into `dev` branch. See the [localization documentation](2_localization.md).
- Full CI build pipeline matrix is activate (see [#1529](https://github.com/bit-team/backintime/issues/1529)).
- Full CI build pipeline matrix is activate (see
[#1529](https://github.com/bit-team/backintime/issues/1529)). This is related
to the Python versions and also to the Ubuntu Distro versions.
- `dev` version was tested (CLI in `common` and GUI in `qt`) and testers/developers agreed on "readiness to be released".


Expand Down Expand Up @@ -301,4 +303,4 @@ To build your own `deb` file see:

https://github.com/bit-team/backintime/blob/dev/CONTRIBUTING.md#build-own-deb-file

<sub>November 2023</sub>
<sub>November 2023</sub>
35 changes: 33 additions & 2 deletions common/schedule.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,10 +136,41 @@ def remove_bit_from_crontab(crontab):


def append_bit_to_crontab(crontab, bit_lines):
# Add a new entry to existing crontab content based on the current
# snapshot profile and its schedule settings.
"""Add new entries to existing crontab content.
Args:
crontab(list): A list of strings as crontab lines.
bit_lines(list): A list of strings as new crontab lines.
Returns:
list: The new crontab lines.
"""
for line in bit_lines:
crontab.append(_MARKER)
crontab.append(line)

return crontab


def is_cron_running():
"""Validate if a cron instance is running.
The output of ``ps`` is searched (case-insensitive) via ``grep`` for the
string ``cron``.
Returns:
bool: The answer.
"""

with subprocess.Popen(['ps', '-eo', 'comm'], stdout=subprocess.PIPE) as ps:
try:
grep = subprocess.run(
['grep', '--ignore-case', 'cron'],
stdin=ps.stdout,
stdout=subprocess.PIPE,
check=True
)
except subprocess.CalledProcessError:
return False

return True
3 changes: 2 additions & 1 deletion common/test/test_lint.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ def test_with_pylint(self):

# Explicit activate checks
err_codes = [
'C0303', # trailing-whitespace
'E0100', # init-is-generator
'E0101', # return-in-init
'E0102', # function-redefined
Expand All @@ -93,7 +94,7 @@ def test_with_pylint(self):
# Enable asap. This list is selection of existing (not all!)
# problems currently exiting in the BIT code base. Quit easy to fix
# because there count is low.
'C0303', # trailing-whitespace
# 'C0304', # missing-final-newline
# 'C0305', # trailing-newlines
# 'C0324', # superfluous-parens
# 'C0410', # multiple-imports
Expand Down
3 changes: 2 additions & 1 deletion qt/test/test_lint.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ def test_with_pylint(self):

# Explicit activate checks
err_codes = [
'C0303', # trailing-whitespace
'E0100', # init-is-generator
'E0101', # return-in-init
'E0102', # function-redefined
Expand All @@ -94,7 +95,7 @@ def test_with_pylint(self):
# Enable asap. This list is selection of existing (not all!)
# problems currently exiting in the BIT code base. Quit easy to fix
# because there count is low.
'C0303', # trailing-whitespace
# 'C0304', # missing-final-newline
# 'C0305', # trailing-newlines
# 'C0324', # superfluous-parens
# 'C0410', # multiple-imports
Expand Down

0 comments on commit 6132d72

Please sign in to comment.