#729 Issue closed
: Confused about the meaning of the has_binary and get_path functions¶
Labels: enhancement
, documentation
, cleanup
,
fixed / solved / done
jsmeix opened issue at 2015-12-02 16:11:¶
In https://github.com/rear/rear/pull/728 I did
has_binary wipefs && REQUIRED_PROGS=( "${REQUIRED_PROGS[@]}" wipefs )
based on what I found in 26_crypt_layout.sh
if ! has_binary cryptsetup; then return fi ... REQUIRED_PROGS=( "${REQUIRED_PROGS[@]}" cryptsetup )
In _input-output-functions.sh there is
# Check if any of the binaries/aliases exist has_binary() { for bin in $@; do if type $bin >&8 2>&1; then return 0 fi done return 1 } get_path() { type -p $1 2>&8 }
Because plain "type" without any option is used
the has_binary function also results true e.g. for aliases
(as mentioned in its comment) and in general for
anything that can be called from a bash prompt
(also functions).
Accordingly I assume the has_binary function is not the right one
to find out if its argument is an executable file that can be added
to the REQUIRED_PROGS array.
It seems get_path is better but even that has strange effects
because "type -p" may output nothing with zero exit code
in some cases:
# type -a test test is a shell builtin test is /usr/bin/test test is /usr/bin/X11/test # type -p test && echo y y # type -P test && echo y /usr/bin/test y
I think the only fail-safe way to test if something is an executable file that can be added to the REQUIRED_PROGS array is "test -P".
jsmeix commented at 2015-12-02 16:12:¶
@gdha @schlomo
could you tell more about the intended usage of the has_binary and
get_path functions?
schlomo commented at 2015-12-02 16:45:¶
has_binary helps you to know if there is a program that you can call. You don't care if it is a shell alias or a file on disk or a shell function, you just want to know if you can call it.
get_path returns you the file path of a program on disk if it is in $PATH
jsmeix commented at 2015-12-03 13:52:¶
Simply put:
REQUIRED_PROGS=( "${REQUIRED_PROGS[@]}" kill )
does not work (no "bin/kill" in recovery system)
while
REQUIRED_PROGS=( "${REQUIRED_PROGS[@]}" /usr/bin/kill )
works.
Details:
My point is that get_path (i.e. "type -p") returns the file path of its argument on disk if it is in $PATH but only when its argument is of type "file".
In contrast to "type -P" that returns the file path of its argument on disk if such a file exists in $PATH.
Accordingly I wonder if "type -p" or "type -P" should be used for the elements in the REQUIRED_PROGS array.
Currently get_path (i.e. "type -p") is used in 39_copy_binaries_libraries.sh
# calculate binaries from needed progs declare -a BINARIES=( $( for bin in "${PROGS[@]}" "${REQUIRED_PROGS[@]}"; do file="$(get_path "$bin")" if [[ -x "$file" ]]; then echo $file echo "Found $file" >&8 fi done | sort -u) )
For normal cases when for an element in REQUIRED_PROGS only an executable file exists, that file gets copied into the recovery system.
But for an exceptional case when for an element in REQUIRED_PROGS both a function or builtin and an executable file exists, then nothing gets copied into the recovery system.
I wonder if that behaviour is right or wrong.
In general when for an element in REQUIRED_PROGS both a function or builtin and an executable file exists one could assume that then those function or builtin is (somehow) automatically available in the recovery system.
This is in particular true for the usual functions in rear (but those functions are normally not specified in REQUIRED_PROGS).
But should we rely on it?
E.g. when a builtin exists but that does not provide features of an executable file so that the executable file is explicitly required.
I think the actual root issue here is that when for an element in REQUIRED_PROGS not only an executable file exists but something else too (e.g. a function or a builtin).
I think the actual problem is what to do if an element in REQUIRED_PROGS does not identify a unique executable.
I think it is impossible to automatically do the right thing in such cases.
Therefore I would like to implement a warning message that is shown if an element in REQUIRED_PROGS does not identify a unique executable.
I would like to show a warning message if "type -a" does not result one single line for an element in REQUIRED_PROGS like:
'kill' specified in REQUIRED_PROGS is ambiguous: kill is a shell builtin kill is /usr/bin/kill kill is /bin/kill Specify it with full path when you need the executable file.
But on the other hand I know your ( @schlomo ) opinion about warning messages and I agree with you in general.
But currently I have no better idea here.
I think silently ignoring ambiguities (as it is now) and let the user find out later the hard way when it does not work is worse than a warning message in this particular case.
schlomo commented at 2015-12-03 14:05:¶
IMHO kill
is not really a valid example. As ReaR actually requires
Bash >= 3 to work we always "ship" the Bash internal commands.
If a user would have a personal shell function mykill
and include that
in REQUIRED_PROGS
then indeed it would not work.
Maybe we can fix that problem when it comes up? Or do you have a specific problem that needs fixing.
Using type -P
might indeed be a good idea. Since which Bash version is
that supported?
jsmeix commented at 2015-12-03 14:40:¶
I have no specific problem that needs fixing
so that there is not any kind of pressure here.
Accordingly I did not set the label "bug" for this issue
but only "enhancement" (and "documentation" if needed).
I think "kill" is a valid example at least on my SLE12 system because:
# help kill kill: kill [-s sigspec | -n signum | -sigspec] pid | jobspec ... or kill -l [sigspec] ... Options: -s sig ... -n sig ... -l
versus
# man kill ... SYNOPSIS kill [-signal|-s signal|-p] [-q value] [-a] [--] pid|name... kill -l [number] | -L ... OPTIONS -s, --signal signal ... -l, --list [number] ... -L, --table ... -a, --all ... -p, --pid ... -q, --queue value
I.e. the kill builtin and /usr/bin/kill support different options.
Meanwhile I also think "type -P" is the right thing.
Reasoning:
When the user specified
REQUIRED_PROGS=( "${REQUIRED_PROGS[@]}" kill )
it is reasonable to assume that his explicit "kill" therein does not
mean
the builtin but the executable file:
# type -P kill /usr/bin/kill
Even if his explicit "kill" therein did mean the builtin, having /usr/bin/kill additionally in the recovery system cannot do any harm because a simple "kill" calls the builtin while /usr/bin/kill would have to be explicitly called with its path.
In the end I think at least in 39_copy_binaries_libraries.sh it is possible to do automatically "the right thing" via
# calculate binaries from needed progs declare -a BINARIES=( $( for bin in "${PROGS[@]}" "${REQUIRED_PROGS[@]}"; do file="$(type -P "$bin")" if [[ -x "$file" ]]; then echo $file echo "Found $file" >&8 fi done | sort -u) )
Currently I do not know if there could be regressions at unexpected places if we change get_path in _input-output-functions.sh to
get_path() { type -P $1 2>&8 }
According to your ( @schlomo ) above description in https://github.com/rear/rear/issues/729#issuecomment-161360329
get_path returns you the file path of a program on disk if it is in $PATH
it matches exactly "type -P" (but not "type -p" in any case):
# help type type: type [-afptP] name [name ...] ... If the -p flag is used, `type' either returns the name of the disk file that would be executed, or nothing if `type -t NAME' would not return `file'. ... The -P flag forces a PATH search for each NAME, even if it is an alias, builtin, or function, and returns the name of the disk file that would be executed.
This is the "help type" output of bash 3.1.17 in SLE10.
jsmeix commented at 2015-12-03 14:48:¶
In the bash-2.05b sources (we have that in SLE9) I found builtins/type.def that contains:
... type [-afptP] name [name ...] ... If the -p flag is used, `type' either returns the name of the disk file that would be executed, or nothing if `type -t NAME' would not return `file'. ... The -P flag forces a PATH search for each NAME, even if it is an alias, builtin, or function, and returns the name of the disk file that would be executed.
schlomo commented at 2015-12-03 14:53:¶
@jsmeix did we already define the oldest OS version we support? That would give you where to check.
BTW, I just realized another probable reason for having get_path
and
has_binary
:
get_path
should be used to copy programs to the rescue system. Here we need the actual path of the file in order to copy it.has_binary
should be used to decide if a a feature is available, e.g.wipefs
. For that we don't care if the program is an alias, a function or an actual file on disk. We just want to know if we can call that program and don't care about the implementation. Very useful to allow users to supply a missing program with a Bash function in ReaR that will do the same job.
I fully understand your arguments. And I am not against using "type -P" if it works also on the oldest supported OS (Thanks for checking SLE9!!). Feel free to make a pull request, as usual.
Let's close this issue till it becomes an actual problem (it helps us all if "open" issues are issues where we still need to do something).
Feel free to reopen it if we should do something.
jsmeix commented at 2015-12-03 15:10:¶
I made my pull request simultaneosly with your comment.
If you like, accept the pull request.
I think using "type -P" instead of "type -p" for get_path()
is a real improvement towards more fail-safe operation.
Even if it is only needed in exceptional cases - but usually
the special use cases are the ones that cause trouble.
jsmeix commented at 2015-12-03 15:12:¶
I think I remember official support for some old distributions was dropped. I think @gdha has mentioned it in the documentation...
jsmeix commented at 2015-12-03 15:16:¶
I found in doc/rear-release-notes.txt
Supported Operating Systems Rear-1.17 is supported on the following Linux based operating systems: Fedora 20, 21 and 22 RHEL 5, 6 and 7 CentOS 5, 6 and 7 ScientificLinux 6 and 7 SLES 11 and 12 OpenSuSe 11, 12 and 13 Debian 6, 7 and 8 Ubuntu 12, 13, 14 and 15 Rear-1.17 dropped officially support for the following Linux based operating systems: Fedora <20 RHEL 3 and 4 SLES 9 and 10 OpenSuSe <11 Debian <6 Ubuntu <12 If you require support for unsupported Linux Operating System you must acquire a rear support contract (per system).
jsmeix commented at 2015-12-03 16:50:¶
With https://github.com/rear/rear/pull/730 the isue should be fixed.
[Export of Github issue for rear/rear.]