How to properly use log_daemon_msg, log_end_msg, log_progress_msg to write a proper daemon script? - daemon

I was suprised not to be able to find any documentation regarding the proper user of these functions:
log_daemon_msg
log_progress_msg
log_end_msg
log_action_msg
log_success_msg
log_failure_msg
log_warning_msg
Where can I find more information about their usage and maybe other related functions?
Note, I found them inside /lib/lsb/init-functions but the is documentation regarding their usage is mostly missing.

I think this is what you are looking for:
http://refspecs.linuxbase.org/LSB_4.1.0/LSB-Core-generic/LSB-Core-generic/iniscrptfunc.html
I've been reading a lot of init scripts on debian wheezy but there doesn't seems to be a unified way of creating init scripts. Some people use echo instead of log_warning_msg or log_failure_msg.
Note: /lib/lsb/init-functions doesn't seem to work well under bash. So remember to use the appropriate shebang:
#!/bin/sh

just try to test that with any script:
vim 123.sh
#!/bin/sh
. /lib/lsb/init-functions
[ 1 != 2 ] && log_end_msg 1
So I`ve included funcs from /lib/lsb/init-functions.
And execute:
bash 123.sh
...fail!
And so on:
cat 123.sh
#!/bin/sh
. /lib/lsb/init-functions
[ 1 != 2 ] && log_end_msg 0
And run:
bash 123.sh
...done.

Related

Autocomplete directories in a subfolder with the Fish shell

I'm having trouble getting the 'complete' function in the fish shell to behave as I would like and I've been searching for an answer for days now.
Summary
Essentially I need to provide tab directory auto-completion as if I was in a different directory to the one I am currently in. It should behave exactly as 'cd' and 'ls' do, but with the starting point in another directory. It seems like such a trivial thing to be able to do but I can't find a way to make it work.
Explanation
Example folder structure below
- root
- foo
- a
- dir1
- subdir1
- dir2
- subdir2
- b
- dir3
- subdir3
- dir4
- subdir4
I am running these scripts whilst in the 'root' directory, but I need tab auto-complete to behave as if I was in the 'foo' directory.
testfunc -d a/dir2/subdir2
Instead of
testfunc -d foo/a/dir2/subdir2
There are a lot of directories inside 'foo' and a lot of sub-directories within them, and this auto-complete behaviour is necessary to speed our process (this script is used extensively throughout the day).
Attempted Solution
I've tried using the 'complete' builtin to get this working by specifying the directory to use, but all this managed to do was auto-complete the first level of directories with a space after the argument instead of continuing to auto-complete like 'cd' would.
complete -x -c testfunc -a "(__fish_complete_directories ./foo/)"
Working bash version
I have already got this working in Bash and I am trying to port it over to fish. See below for the Bash version.
_testfunc()
{
local cur prev words cword
_init_completion || return
compopt +o default
case $prev in
testfunc)
COMPREPLY=( $( compgen -W '-d' -- "$cur" ) )
compopt +o nospace
return
;;
-d)
curdir=$(pwd)
cd foo/ 2>/dev/null && _filedir -d
COMPREPLY=( $( compgen -d -S / -- "$cur" ) )
cd $curdir
return
;;
esac
} &&
complete -o nospace -F _testfunc testfunc
This is essentially stepping into the folder that I want, doing the autocompletion, then stepping back into the original folder that the script was run in. I was hoping this would be easier in Fish after getting it working in Bash (I need to support these two shells), but I'm just pulling my hair out.
Any help would be really appreciated!
I am not a bash completions expert, but it looks like the bash completions are implemented by changing directories, running completions, and then changing back. You can do the same in fish:
function complete_testfunc
set prevdir $PWD
cd foo
__fish_complete_directories
cd $prevdir
end
complete -x -c testfunc -a "(complete_testfunc)"
does that work for you?

cpack restrict OS version package can be installed on

I create packages for several OS versions including RHEL7 & RHEL8 (or mostly equally CentOS7 & 8).
It is possible to install a package built for .el7. on .el8. but it will typically not work (for example due to undefined symbols etc).
Ideally I would like to make the installation fail with an error message like "this package is only intend for RHEL7/CentOS7".
How can I do this?
More specifically how can I do this with CPack/CMake?
Bonus points if you can also given an explanation suitable for Debian versions.
Here are some ideas I have so far:
Use dist tags somehow, see:
https://serverfault.com/questions/283330/rpm-spec-conditional-require-based-of-distro-version
Check uname -r at install time in a pre-install script
Part of that answer is here:
How to check os version in rpmbuild spec file
https://unix.stackexchange.com/questions/9296/how-can-i-specify-os-conditional-build-requirements-in-an-rpm-spec-file
I'm not quite sure how to do that using cpack. I do not want to generate a custom spec file as the build machinery is already complex enough.
Another option would be to add a %requires on a package that only exists on RHEL7 but not RHEL8 or visa versa. That package would need to also exist on CentOS and not change in a way that would make the installation fail if it is upgraded. Does anyone know a suitable package to depend on?
For example:
>rpm -q --whatprovides /etc/redhat-release
centos-release-8.2-2.2004.0.1.el8.x86_64
This looks like a good candidate but if I add a dependency on centos-release-8.2 and they later upgrade to centos-release-8.3 or use RedHat instead this will not work.
I did this before by having a stanza in %pre that stopped it:
if [ -n "%{dist}" ]; then
PKG_VER=`echo %{dist} | perl -ne '/el(\d)/ && print $1'`
THIS_VER=`perl -ne '/release (\d)/ && print $1' /etc/redhat-release`
if [ -n "${PKG_VER}" -a -n "${THIS_VER}" ]; then
if [ ${PKG_VER} -ne ${THIS_VER} ]; then
for i in `seq 20`; do echo ""; done
echo "WARNING: This RPM is for CentOS${PKG_VER}, but you seem to be running CentOS${THIS_VER}" >&2
echo "You might want to uninstall these RPMs immediately and get the CentOS${THIS_VER} version." >&2
for i in `seq 5`; do echo "" >&2; done
fi
fi
fi
Remember - you cannot have any user interaction in RPM installation. You could have it fail instead of warn tho; that's up to you.

How to solve CTRL-t key binding issue for fzf?

I recently found this command line tool called fzf. I installed it according to the instructions and it does work, except for the CTRL-T key binding. Even though, I installed the special stuff with the key bindings as per their instructions, and I also tried installing fzf downloaded from the git repo as opposed to via homebrew, all the CTRL-T key binding does, still, is swap the last two characters.
I found this discussion about this, but none of the answers offered worked for me.
edit: you can see it in the first video here what I want to achieve.
edit 2: I'm using the Terminal of MacOs.
I use zsh with Oh My Zsh on Mac.
If I put fzf before vi-mode in the plugin setting in .zshrc like
plugins=(... fzf ... vi-mode ...)
Ctrl-t does not work showing ^T. Ctrl-r does not work, either.
But, if fzf comes AFTER vi-mode like
plugins=(... vi-mode ... fzf ...)
no problem arises.
If you clone fzf from the repository it contains a file called fzf/shell/key-bindings.zsh which refers to
fzf-file-widget() {
LBUFFER="${LBUFFER}${__fsel}"
local ret=$?
zle redisplay
typeset -f zle-line-init >/dev/null && zle-line-init
return $ret
}
zle -N fzf-file-widget
bindkey "^T" fzf-file-widget
the Control-T keybinding. This is normally sourced by your .zshrc
[ -f ~/.fzf.zsh ] && source ~/.fzf.zsh
which should contain its reference in .fzf.zsh:
source "$HOME/.fzf/shell/key-bindings.zsh"
If your keybinding does not work then your keybinding may be overwritten by your zshrc or may not be invoked by your zshrc.
If you are using zsh-vi-mode, then replace this line
[ -f ~/.fzf.zsh ] && source ~/.fzf.zsh
with this
zvm_after_init_commands+=('[ -f ~/.fzf.zsh ] && source ~/.fzf.zsh')
From zsh-vi-mode GitHub page
Psst! if you use fzf-tab, you might want to enable that also
zvm_after_init_commands+=('[ -f ~/.fzf.zsh ] && source ~/.fzf.zsh && enable-fzf-tab')
I put the below script in my .zshrc and sourced it using source ~/.zshrc
if [ -x "$(command -v fzf)" ]
then
source /usr/share/fzf/key-bindings.zsh
fi
and now key bindings (CTRL-T, CTRL-R, and ALT-C) work for me.
got the above script from how to enable hotkeys for fzf
explanation
you have key-bindings.zsh inside /usr/share/fzf or a few directories deeper.
Above script only sources key-bindings.zsh if fzf is installed.
rest of the working is part of the key-bindings.zsh, which frankly I did not bother to
understand.
OS: Manjaro GNU-Linux
I have noticed CTRL-T does not work (in bash) when I have the "vi mode" enabled by set -o vi.
I managed to make the CTRL-t key combo work as desired. There was one step I had missed.
After installing useful keybindings and fuzzy completion with /usr/local/opt/fzf/install, I updated fzf.bash manually with [ -f ~/.fzf.bash ] && source ~/.fzf.bash. After restarting the Terminal, it now works.
Edit: Also, this line needs to be added to your .bash_profile or .bashrc: source ~/.fzf.bash.

Including some SFTP commands in a Makefile

I use a Makefile to create pdfs of papers I'm working on. I'd also like to use make to upload the latest version to my website, which requires sftp. I though I could do something like this (which words on the command line) but it seems that in make, the EOF is getting ignored i.e., this
website:
sftp -oPort=2222 me#mywebsite.com << EOF
cd papers
put research_paper.pdf
EOF
generates an error message
cd papers
/bin/sh: line 0: cd: papers: No such file or directory
which I think is saying "papers" doesn't exist on your local machine i.e., the 'cd' is being executed locally, not remotely.
Couple of ideas:
use ncftp which every Linux distro as well as brew should have: it remembers 'state' so the cd becomes unnecessary
use scp instead of sftp if possible
write a trivial shell script doing the EOF business and call that
For what it is worth, here is my script to push tarballs to the CRAN winbuilder -- and takes target directory and script as arguments to ncftpput.
#!/bin/bash
function errorexit () {
echo "Error: $1"
exit 1
}
if [ "$#" -lt 1 ]; then
errorexit "Need to specify argument file"
fi
if [ ! -f ${1} ]; then
errorexit "File ${1} not found, aborting."
fi
ncftpput win-builder.r-project.org /R-release ${1}
ncftpput win-builder.r-project.org /R-devel ${1}
I then just do wbput.sh foo_1.2-3.tar.gz and off it goes...
You cannot (normally) put a single command on multiple lines in a Make recipe, so here documents are a no-go. Try this instead:
website: research_paper.pdf
printf 'cd papers\nput $<\n' \
| sftp -oPort=2222 me#mywebsite.com
The target obviously depends on the PDF, so I made it an explicit dependency, as well.

ksh error remove from list

I am trying to remove a certain element from a list in korn shell. It's working on my linux machine but the exact same code gives me an error on a solaris11 machine. I need a code that will work for both. It's probably because of different ksh versions but I would like to find a solution that works for both.
The code is:
#!/bin/ksh
MY_LIST="HELLO HOW ARE YOU"
toDel="HOW"
MY_LIST=( "${MY_LIST[#]/$toDel}" )
echo "MY LIST AFTER REMOVING HOW IS $MY_LIST"
On Solaris I get the following error:
syntax error at line 4 : '(' unexpected
Any suggestions?
Melodie wrote: Finally, I used 'Walter A' solution
Nice I could help.
Enabling you to vote for me and close the question, I post my comment as an answer.
MY_LIST=`echo $MY_LIST | sed "s/$toDel//"`
You'll probably need to spend some time with the ksh88 man page.
Without futher explanation:
set -A my_list HELLO HOW ARE YOU # note, separate words
toDel=HOW
set -- # using positional parameters as "temp array"
for word in "${my_list[#]}"; do
[[ $word != $toDel ]] && set -- "$#" "$word"
done
set -A my_list "$#"
printf "%s\n" "${my_list[#]}"
HELLO
ARE
YOU
Finally, I used 'Walter A' solution:
MY_LIST=`echo $MY_LIST | sed "s/$toDel//"`