Skip to content

Commit

Permalink
fix: Debug output with version, name, run-as-root and OS
Browse files Browse the repository at this point in the history
The debug output now contains minimal diagnostic information about appliation name, version, if it runs as root and the operating system.

- Separated code from `collect_diagnostics()` into `collect_minimal_diagnostics()` which is then called in `common/backintime.py::startApp()` to build a debug message.
- Fixed an the user-callback unit tests introduced in #1658
- Minor refactoring and minor mods in README.md and CONTRIBUTING.md.

Fix #1664
Improve PR #1658
  • Loading branch information
buhtz committed Mar 15, 2024
1 parent 1150ffb commit e818aeb
Show file tree
Hide file tree
Showing 17 changed files with 198 additions and 104 deletions.
4 changes: 2 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,9 @@ jobs:
python: "3.12"

install:
- pip install pylint coveralls pyfakefs
- pip install pylint coveralls pyfakefs keyring
# PyQt is not available for "ppc64le" architecture on PyPi
- if [ "$TRAVIS_ARCH" != "ppc64le" ] ; then pip install pyqt6; fi
- if [ "$TRAVIS_ARCH" != "ppc64le" ] ; then pip install pyqt6 dbus-python; fi
# add ssh public / private key pair to ensure user can start ssh session to localhost for tests
- ssh-keygen -b 2048 -t rsa -f /home/travis/.ssh/id_rsa -N ""
- cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
Expand Down
6 changes: 3 additions & 3 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,8 @@ replaced with PyPi packages.
- `python3-dbus.mainloop.pyqt6`
- `libnotify-bin`
- `policykit-1`
- `qttranslations5-l10n`
- `qtwayland5` (if Wayland is used as display server instead of X11)
- `qttranslations6-l10n`
- `qtwayland6` (if Wayland is used as display server instead of X11)
- Recommended
- For SSH key storage **one** of these packages
- `python3-secretstorage`
Expand Down Expand Up @@ -151,4 +151,4 @@ Keep in mind as you contribute, that code, docs and other material submitted
to the project are considered licensed under the same terms (see
[LICENSE](LICENSE)) as the rest of the work.

<sub>Sept 2023</sub>
<sub>March 2024</sub>
41 changes: 23 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,15 @@
<sub>Copyright (C) 2008-2024 Oprea Dan, Bart de Koning, Richard Bailey,
Germar Reitze, Taylor Raack, Christian Buhtz, Michael Büker, Jürgen Altfeld<sub>

_Back In Time_ is an easy-to-use backup tool for files and folders.
_Back In Time_ is an easy-to-use tool to backup files and folders.
It runs on GNU Linux (not on Windows or OS X/macOS) and provides a command line tool `backintime` and a
GUI `backintime-qt` both written in Python3. It uses
[`rsync`](https://rsync.samba.org/) to take manual or scheduled snapshots and
stores them locally or remotely through SSH. Each snapshot is in its own folder
with copies of the original files, but unchanged files are hard-linked between
snapshots to save space.
snapshots to save storage space.
It was inspired by [FlyBack](https://en.wikipedia.org/wiki/FlyBack).

You only need to specify 3 things:

* What folders to back up.
* Where to save snapshots.
* The backup frequency (manual, every hour, every day, every month).

## Maintenance status

A small team (Christian Buhtz, Michael Büker and Jürgen Altfeld)
Expand All @@ -37,7 +31,7 @@ instead of implementing new
If you are interested in the development, please
see [CONTRIBUTING](CONTRIBUTING.md) and have a look on
[open issues](https://github.com/bit-team/backintime/issues) especially
those labeled as [good first](https://github.com/bit-team/backintime/labels/GOOD%20FIRST%20ISSUE)
those labeled as [good first issue](https://github.com/bit-team/backintime/labels/GOOD%20FIRST%20ISSUE)
and [help wanted](https://github.com/bit-team/backintime/issues?q=is%3Aissue+is%3Aopen+label%3AHELP-WANTED).

## Index
Expand All @@ -49,14 +43,15 @@ and [help wanted](https://github.com/bit-team/backintime/issues?q=is%3Aissue+is%

## Documentation, FAQs, Support

* [End user documentation](https://backintime.readthedocs.org/) (not totally up-to-date)
* [FAQ - Frequently Asked Questions](FAQ.md)
* [Source code documentation for developers](https://backintime-dev.readthedocs.org)
* Use [Issues](https://github.com/bit-team/backintime/issues) to ask questions and report bugs.
* [End user documentation](https://backintime.readthedocs.org/) (not totally up-to-date)
* [Mailing list
_bit-dev_](https://mail.python.org/mailman3/lists/bit-dev.python.org/) for
**every topic**, question and idea about _Back In Time_. Despite its name
it is not restricted to development topics only.
* Use [Issues](https://github.com/bit-team/backintime/issues) to ask
questions and report bugs.
* [Source code documentation for developers](https://backintime-dev.readthedocs.org)

## Installation

Expand All @@ -77,11 +72,11 @@ installation options provided and maintained by third parties.

In the latest stable release:
- [File permissions handling and therefore possible non-differential backups](#file-permissions-handling-and-therefore-possible-non-differential-backups)
- RTE "module 'qttools' has no attribute 'initate_translator'" with encFS when prompting the user for a password (#1553)
- [Warning: apt-key is deprecated. Manage keyring files in trusted.gpg.d instead (see apt-key(8)).](#warning-apt-key-is-deprecated-manage-keyring-files-in-trustedgpgd-instead-see-apt-key8)
- [`qt5_probing.py` may hang with high CPU usage when running BiT as `root` via `cron`](#qt5_probingpy-may-hang-with-high-cpu-usage-when-running-bit-as-root-via-cron)

In older releases:
- RTE "module 'qttools' has no attribute 'initate_translator'" with encFS when prompting the user for a password ([#1553](https://github.com/bit-team/backintime/issues/#1553))
- [Tray icon or other icons not shown correctly](#tray-icon-or-other-icons-not-shown-correctly)
- [Non-working password safe and BiT forgets passwords (keyring backend issues)](#non-working-password-safe-and-bit-forgets-passwords-keyring-backend-issues)
- [Incompatibility with rsync >= 3.2.4](#incompatibility-with-rsync-324-or-newer)
Expand Down Expand Up @@ -120,7 +115,7 @@ This issue is tracked in [#1338](https://github.com/bit-team/backintime/issues/1

#### `qt5_probing.py` may hang with high CPU usage when running BiT as `root` via `cron`

See the related issue #1592
See the related issue [#1592](https://github.com/bit-team/backintime/issues/1592).

The only reliable work-around is to delete (or move into another folder)
the file `/usr/share/backintime/common/qt5_probing.py`:
Expand Down Expand Up @@ -184,15 +179,25 @@ See also issue [#1321](https://github.com/bit-team/backintime/issues/1321)

#### Incompatibility with rsync 3.2.4 or newer

The release (`1.3.2`) and earlier versions of _Back In Time_ are incompatible with `rsync >= 3.2.4` ([#1247](https://github.com/bit-team/backintime/issues/1247)). The problem is [fixed](https://github.com/bit-team/backintime/pull/1351) in the current master branch of that repo and will be released with the next release (`1.3.3`) of _Back In Time_.
**Status: Fixed in v1.3.3**

The release (`1.3.2`) and earlier versions of _Back In Time_ are incompatible
with `rsync >= 3.2.4`
([#1247](https://github.com/bit-team/backintime/issues/1247)).

If you use `rsync >= 3.2.4` and `backintime <= 1.3.2` there is a workaround. Add `--old-args` in [_Expert Options_ / _Additional options to rsync_](https://backintime.readthedocs.io/en/latest/settings.html#expert-options). Note that some GNU/Linux distributions (e.g. Manjaro) using a workaround with environment variable `RSYNC_OLD_ARGS` in their distro-specific packages for _Back In Time_. In that case you may not see any problems.
If you use `rsync >= 3.2.4` and `backintime <= 1.3.2` there is a
workaround. Add `--old-args` in
[_Expert Options_ / _Additional options to rsync_](https://backintime.readthedocs.io/en/latest/settings.html#expert-options).
Note that some GNU/Linux distributions (e.g. Manjaro) using a workaround with
environment variable `RSYNC_OLD_ARGS` in their distro-specific packages for
_Back In Time_. In that case you may not see any problems.

#### Python 3.10 compatibility and Ubuntu version

_Back In Time_ versions older than 1.3.2 do not start with Python >= 3.10.
Ubuntu 22.04 LTS ships with Python 3.10 and backintime 1.2.1, but has applied
[a patch](https://bugs.launchpad.net/ubuntu/+source/backintime/+bug/1976164/+attachment/5593556/+files/backintime_1.2.1-3_1.2.1-3ubuntu0.1.diff)
to make it work. If you want to update to backintime 1.3.2 in Ubuntu, you may use the PPA: see under [`INSTALL/Ubuntu PPA`](#Ubuntu-PPA).
to make it work. If you want to update _Back In Time_, you may use one of the
[alternative options for installation](#alternative-installation-options).

<sub>Jan 2024</sub>
<sub>March 2024</sub>
68 changes: 43 additions & 25 deletions common/backintime.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
import password
import encfstools
import cli
from diagnostics import collect_diagnostics
from diagnostics import collect_diagnostics, collect_minimal_diagnostics
from exceptions import MountException
from applicationinstance import ApplicationInstance
from version import __version__
Expand Down Expand Up @@ -504,24 +504,29 @@ def startApp(app_name = 'backintime'):

logger.openlog()

#parse args
args = argParse(None)

#add source path to $PATH environ if running from source
# Name, Version, As Root, OS
diag = collect_minimal_diagnostics()
logger.debug(
f'{diag["backintime"]} {list(diag["host-setup"]["OS"].values())}')

# Add source path to $PATH environ if running from source
if tools.runningFromSource():
tools.addSourceToPathEnviron()

#warn about sudo
# Warn about sudo
if tools.usingSudo() and os.getenv('BIT_SUDO_WARNING_PRINTED', 'false') == 'false':
os.putenv('BIT_SUDO_WARNING_PRINTED', 'true')
logger.warning("It looks like you're using 'sudo' to start %(app)s. "
"This will cause some trouble. Please use either 'sudo -i %(app_name)s' "
"or 'pkexec %(app_name)s'."
%{'app_name': app_name, 'app': config.Config.APP_NAME})

#call commands
# Call commands
if 'func' in dir(args):
args.func(args)

else:
setQuiet(args)
printHeader()
Expand Down Expand Up @@ -550,51 +555,64 @@ def join(args, subArgs):
that should be merged into ``args``
"""
for key, value in vars(subArgs).items():
#only add new values if it isn't set already or if there really IS a value
# Only add new values if it isn't set already or if there really IS
# a value
if getattr(args, key, None) is None or value:
setattr(args, key, value)

#first parse the main parser without subparsers
#otherwise positional args in subparsers will be to greedy
#but only if -h or --help is not involved because otherwise
#help will not work for subcommands
# First parse the main parser without subparsers
# otherwise positional args in subparsers will be to greedy
# but only if -h or --help is not involved because otherwise
# help will not work for subcommands
mainParser = parsers['main']
sub = []

if '-h' not in sys.argv and '--help' not in sys.argv:

for i in mainParser._actions:

if isinstance(i, argparse._SubParsersAction):
#remove subparsers
# Remove subparsers
mainParser._remove_action(i)
sub.append(i)

args, unknownArgs = mainParser.parse_known_args(args)
#read subparsers again

# Read subparsers again
if sub:
[mainParser._add_action(i) for i in sub]

#parse it again for unknown args
# Parse it again for unknown args
if unknownArgs:
subArgs, unknownArgs = mainParser.parse_known_args(unknownArgs)
join(args, subArgs)

#finally parse only the command parser, otherwise we miss
#some arguments from command
# Finally parse only the command parser, otherwise we miss some arguments
# from command
if unknownArgs and 'command' in args and args.command in parsers:
commandParser = parsers[args.command]
subArgs, unknownArgs = commandParser.parse_known_args(unknownArgs)
join(args, subArgs)

if 'debug' in args:
try:
logger.DEBUG = args.debug

dargs = vars(args)
logger.debug('Arguments: %s | unknownArgs: %s'
%({arg:dargs[arg] for arg in dargs if dargs[arg]},
unknownArgs))

#report unknown arguments
#but not if we run aliasParser next because we will parse again in there
except AttributeError:
pass

args_dict = vars(args)
used_args = {
key: args_dict[key]
for key
in filter(lambda key: args_dict[key] is not None, args_dict)
}
logger.debug(f'Used argument(s): {used_args}')
logger.debug(f'Unknown argument(s): {unknownArgs}')

# Report unknown arguments but not if we run aliasParser next because we
# will parse again in there.
if unknownArgs and not ('func' in args and args.func is aliasParser):
mainParser.error('Unknown Argument(s): %s' % ', '.join(unknownArgs))
mainParser.error(f'Unknown argument(s): {unknownArgs}')

return args

def printHeader():
Expand Down
1 change: 1 addition & 0 deletions common/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ def __init__(self, config_path=None, data_path=None):
tools.makeDirs(self._LOCAL_MOUNT_ROOT)

self._DEFAULT_CONFIG_PATH = os.path.join(self._LOCAL_CONFIG_FOLDER, 'config')

if config_path is None:
self._LOCAL_CONFIG_PATH = self._DEFAULT_CONFIG_PATH
else:
Expand Down
Loading

0 comments on commit e818aeb

Please sign in to comment.