Matching package version string in /bin/sh - regex

I'm trying to match given string and match it to a package version in a /bin/sh script:
if test "x$version" = "x"; then
version="latest";
info "Version parameter not defined, assuming latest";
else
info "Version parameter defined: $version";
info "Matching version to package version"
case "$version" in
[^4.0.]*)
$package_version='1.0.1'
;;
[^4.1.]*)
$package_version='1.1.1'
;;
[^4.2.]*)
$package_version='1.2.6'
;;
*)
critical "Unable to match requested version to package version"
exit 1
;;
esac
fi
However, when I run it I get an error:
23:38:47 +0000 INFO: Version parameter defined: 4.0.0
23:38:47 +0000 INFO: Matching Puppet version to puppet-agent package version (See http://docs.puppetlabs.com/puppet/latest/reference/about_agent.html for more details)
23:38:47 +0000 CRIT: Unable to match requested puppet version to puppet-agent version - Check http://docs.puppetlabs.com/puppet/latest/reference/about_agent.html
23:38:47 +0000 CRIT: Please file a bug report at https://github.com/petems/puppet-install-shell/
23:38:47 +0000 CRIT:
23:38:47 +0000 CRIT: Version: 4.0.0
I'm using the same regex that worked for me in another part of the script:, and it seems to work there:
if test "$version" = 'latest'; then
apt-get install -y puppet-common puppet
else
case "$version" in
[^2.7.]*)
info "2.7.* Puppet deb package tied to Facter < 2.0.0, specifying Facter 1.7.4"
apt-get install -y puppet-common=$version-1puppetlabs1 puppet=$version-1puppetlabs1 facter=1.7.4-1puppetlabs1 --force-yes
;;
*)
apt-get install -y puppet-common=$version-1puppetlabs1 puppet=$version-1puppetlabs1 --force-yes
;;
esac
fi
What am I missing?
Full version of the script is here: https://github.com/petems/puppet-install-shell/blob/fix_puppet_agent_install/install_puppet_agent.sh

case ... esac in a POSIX shell script uses (glob-style) patterns, not regular expressions (while the two are distantly related, there are fundamental differences).
To get true regex matching in a sh script, you'd have to use expr with :, though it's probably not needed here.
To test for a prefix match, use <prefix>* in a case branch - case branches are always matched against the entire argument - no need for anchoring (which patterns don't support).
As an aside, what you're attempting would not even work for prefix matching as a regex. E.g., [^4.0.] is the same as [^.04] - i.e., a negated character class: it matches one character if it is neither . nor 0 nor 4.
When assigning to a variable in a POSIX shell script, do not use $.
To put it all together:
#/bin/sh
if [ "$version" = "" ]; then
version="latest";
info "Version parameter not defined, assuming latest"
else
info "Version parameter defined: $version";
info "Matching version to package version"
case "$version" in
4.0.*)
package_version='1.0.1'
;;
4.1.*)
package_version='1.1.1'
;;
4.2.*)
package_version='1.2.6'
;;
*)
critical "Unable to match requested version to package version"
exit 1
;;
esac
fi

Related

GKE cluster using gitbash tool

I have my python3.7 installed on following path on my windows - C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Python 3.7
I am trying to connect GCP GKE cluster using GitBash and when i run below gcloud command to connect GKE cluster i am getting an python not found error.
$ gcloud container clusters get-credentials appcluster --region us-east4 --project dev /c/Users/surendar/AppData/Local/Google/Cloud SDK/google-cloud-sdk/bin/gcloud: line 181: exec: python: not found
Any suggestion's please to resolve the error?
Below is the Google/Cloud SDK/google-cloud-sdk/bin/gcloud file
181 line points to below declaration which is last line of the file
exec "$CLOUDSDK_PYTHON" $CLOUDSDK_PYTHON_ARGS "${CLOUDSDK_ROOT_DIR}/lib/gcloud.py
# Copyright 2013 Google Inc. All Rights Reserved.
#
# <cloud-sdk-sh-preamble>
#
# CLOUDSDK_ROOT_DIR (a) installation root dir
# CLOUDSDK_PYTHON (u) python interpreter path
# CLOUDSDK_GSUTIL_PYTHON (u) python interpreter path for gsutil
# CLOUDSDK_PYTHON_ARGS (u) python interpreter arguments
# CLOUDSDK_PYTHON_SITEPACKAGES (u) use python site packages
# CLOUDSDK_BQ_PYTHON (u) python interpreter for bq
# CLOUDSDK_ENCODING (u) python io encoding for gcloud
#
# (a) always defined by the preamble
# (u) user definition overrides preamble
# Wrapper around 'which' and 'command -v', tries which first, then falls back
# to command -v
_cloudsdk_which() {
which "$1" 2>/dev/null || command -v "$1" 2>/dev/null
}
# Check whether passed in python command reports major version 3.
_is_python3() {
echo "$("$1" -V 2>&1)" | grep -E "Python 3" > /dev/null
}
# For Python 3, gsutil requires Python 3.5+.
_py3_interpreter_compat_with_gsutil () {
# Some environments (e.g. macOS) don't support grep -P, so we use grep -E.
echo "$("$1" -V 2>&1)" | grep -E "Python 3[.]([5-9]|[1-9][0-9])" > /dev/null
}
order_python() {
selected_version=""
for python_version in "$#"
do
if [ -z "$selected_version" ]; then
if _cloudsdk_which $python_version > /dev/null && "$python_version" -c "import sys; print(sys.version)" > /dev/null; then
selected_version=$python_version
fi
fi
done
if [ -z "$selected_version" ]; then
selected_version=python
fi
echo $selected_version
}
# Determines the real cloud sdk root dir given the script path.
# Would be easier with a portable "readlink -f".
_cloudsdk_root_dir() {
case $1 in
/*) _cloudsdk_path=$1
;;
*/*) _cloudsdk_path=$PWD/$1
;;
*) _cloudsdk_path=$(_cloudsdk_which $1)
case $_cloudsdk_path in
/*) ;;
*) _cloudsdk_path=$PWD/$_cloudsdk_path ;;
esac
;;
esac
_cloudsdk_dir=0
while :
do
while _cloudsdk_link=$(readlink "$_cloudsdk_path")
do
case $_cloudsdk_link in
/*) _cloudsdk_path=$_cloudsdk_link ;;
*) _cloudsdk_path=$(dirname "$_cloudsdk_path")/$_cloudsdk_link ;;
esac
done
case $_cloudsdk_dir in
1) break ;;
esac
if [ -d "${_cloudsdk_path}" ]; then
break
fi
_cloudsdk_dir=1
_cloudsdk_path=$(dirname "$_cloudsdk_path")
done
while :
do case $_cloudsdk_path in
*/) _cloudsdk_path=$(dirname "$_cloudsdk_path/.")
;;
*/.) _cloudsdk_path=$(dirname "$_cloudsdk_path")
;;
*/bin) dirname "$_cloudsdk_path"
break
;;
*) echo "$_cloudsdk_path"
break
;;
esac
done
}
CLOUDSDK_ROOT_DIR=$(_cloudsdk_root_dir "$0")
setup_cloudsdk_python() {
# if $CLOUDSDK_PYTHON is not set, look for bundled python else
# prefer python3 over python2
if [ -z "$CLOUDSDK_PYTHON" ]; then
# Is bundled python present?
if [ -x "$CLOUDSDK_ROOT_DIR/platform/bundledpythonunix/bin/python3" ];
then
CLOUDSDK_PYTHON="$CLOUDSDK_ROOT_DIR/platform/bundledpythonunix/bin/python3"
CLOUDSDK_PYTHON_SITEPACKAGES=1
else
CLOUDSDK_PYTHON=$(order_python python3 python2 python2.7 python)
fi
fi
}
setup_cloudsdk_python
# $PYTHONHOME can interfere with gcloud. Users should use
# CLOUDSDK_PYTHON to configure which python gcloud uses.
unset PYTHONHOME
# if CLOUDSDK_PYTHON_SITEPACKAGES and VIRTUAL_ENV are empty
case :$CLOUDSDK_PYTHON_SITEPACKAGES:$VIRTUAL_ENV: in
:::) # add -S to CLOUDSDK_PYTHON_ARGS if not already there
case " $CLOUDSDK_PYTHON_ARGS " in
*" -S "*) ;;
" ") CLOUDSDK_PYTHON_ARGS="-S"
;;
*) CLOUDSDK_PYTHON_ARGS="$CLOUDSDK_PYTHON_ARGS -S"
;;
esac
unset CLOUDSDK_PYTHON_SITEPACKAGES
;;
*) # remove -S from CLOUDSDK_PYTHON_ARGS if already there
while :; do
case " $CLOUDSDK_PYTHON_ARGS " in
*" -S "*) CLOUDSDK_PYTHON_ARGS=${CLOUDSDK_PYTHON_ARGS%%-S*}' '${CLOUDSDK_PYTHON_ARGS#*-S} ;;
*) break ;;
esac
done
# if CLOUDSDK_PYTHON_SITEPACKAGES is empty
[ -z "$CLOUDSDK_PYTHON_SITEPACKAGES" ] &&
CLOUDSDK_PYTHON_SITEPACKAGES=1
export CLOUDSDK_PYTHON_SITEPACKAGES
;;
esac
# Allow users to set the Python interpreter used to launch gsutil, falling
# back to the CLOUDSDK_PYTHON interpreter otherwise.
if [ -z "$CLOUDSDK_GSUTIL_PYTHON" ]; then
CLOUDSDK_GSUTIL_PYTHON="$CLOUDSDK_PYTHON"
fi
if [ -z "$CLOUDSDK_BQ_PYTHON" ]; then
CLOUDSDK_BQ_PYTHON="$CLOUDSDK_PYTHON"
fi
if [ -z "$CLOUDSDK_ENCODING" ]; then
if [ -z "$PYTHONIOENCODING" ]; then
CLOUDSDK_ENCODING=UTF-8
else
CLOUDSDK_ENCODING="$PYTHONIOENCODING"
fi
fi
export CLOUDSDK_ROOT_DIR
export CLOUDSDK_PYTHON_ARGS
export CLOUDSDK_GSUTIL_PYTHON
export CLOUDSDK_BQ_PYTHON
export CLOUDSDK_ENCODING
export PYTHONIOENCODING="$CLOUDSDK_ENCODING"
case $HOSTNAME in
*.corp.google.com|*.c.googlers.com) export CLOUDSDK_GOOGLE_AUTH_IS_GOOGLE_DOMAIN=true;;
esac
# </cloud-sdk-sh-preamble>
exec "$CLOUDSDK_PYTHON" $CLOUDSDK_PYTHON_ARGS "${CLOUDSDK_ROOT_DIR}/lib/gcloud.py"** "$#"```
You will need to point the environment variable CLOUDSDK_PYTHON at your Python executable (e.g. python.exe). To find the Python executable, you should be able to right-click on "Python 3.7" in the start menu and look at "Target".
In my case, the Python executable is located at C:\Users\g_r_s\AppData\Local\Programs\Python\Python37\python.exe
Using Git Bash, you can export CLOUDSDK_PYTHON
$ export CLOUDSDK_PYTHON=/c/Users/g_r_s/AppData/Local/Programs/Python/Python37/python.exe
$ gcloud version
Google Cloud SDK 344.0.0
beta 2021.06.04
bq 2.0.69
core 2021.06.04
gsutil 4.62
NOTE: You can also try installing the bundled Python when you install the SDK on Windows as well.

if condition to folder branch in Jenkinsfile

I have branch folder "feature-set" under this folder there's multibranch
I need to run the below script in my Jenkinsfile with a condition if this build runs from any branches under the "feature-set" folder like "feature-set/" then run the script
the script is:
sh """
if [ ${env.BRANCH_NAME} = "feature-set*" ]
then
echo ${env.BRANCH_NAME}
branchName='${env.BRANCH_NAME}' | cut -d'\\/' -f 2
echo \$branchName
npm install
ng build --aot --output-hashing none --sourcemap=false
fi
"""
the current output doesn't get the condition:
[ feature-set/swat5 = feature-set* ]
any help?
I would re-write this to be primarily Jenkins/Groovy syntax and only go to shell when required.
Based on the info you provided I assume your env.BRANCH_NAME always looks like `feature-set/
// Echo first so we can see value if condition fails
echo(env.BRANCH_NAME)
// startsWith better than contains() based on current usecase
if ( (env.BRANCH_NAME).startsWith('feature-set') ) {
// Split branch string into list based on delimiter
List<String> parts = (env.BRANCH_NAME).tokenize('/')
/**
* Grab everything minus the first part
* This handles branches that include additional '/' characters
* e.g. 'feature-set/feat/my-feat'
*/
branchName = parts[1..-1].join('/')
echo(branchName)
sh('npm install && ng build --aot --output-hashing none --sourcemap=false')
}
This seems to be more on shell side. Since you are planning to use shell if condition the below worked for me.
Administrator1#XXXXXXXX:
$ if [[ ${BRANCH_NAME} = feature-set* ]]; then echo "Success"; fi
Success
Remove the quotes and add an additional "[]" at the start and end respectively.
The additional "[]" works as regex

Script execution using ansible [duplicate]

I am using Ansible to deploy my project and I trying to check if an specified package is installed, but I have a problem with it task, here is the task:
- name: Check if python-apt is installed
command: dpkg -l | grep python-apt
register: python_apt_installed
ignore_errors: True
And here is the problem:
$ ansible-playbook -i hosts idempotent.yml
PLAY [lxc-host] ***************************************************************
GATHERING FACTS ***************************************************************
ok: [10.0.3.240]
TASK: [idempotent | Check if python-apt is installed] *************************
failed: [10.0.3.240] => {"changed": true, "cmd": ["dpkg", "-l", "|", "grep", "python-apt"], "delta": "0:00:00.015524", "end": "2014-07-10 14:41:35.207971", "rc": 2, "start": "2014-07-10 14:41:35.192447"}
stderr: dpkg-query: error: package name in specifier '|' is illegal: must start with an alphanumeric character
...ignoring
PLAY RECAP ********************************************************************
10.0.3.240 : ok=2 changed=1 unreachable=0 failed=0
Why is illegal this character '|' .
From the doc:
command - Executes a command on a remote node
The command module takes the command name followed by a list of
space-delimited arguments. The given command will be executed on all
selected nodes. It will not be processed through the shell, so
variables like $HOME and operations like "<", ">", "|", and "&" will
not work (use the shell module if you need these features).
shell - Executes a commands in nodes
The shell module takes the command name followed by a list of space-delimited arguments.
It is almost exactly like the command module but runs the command
through a shell (/bin/sh) on the remote node.
Therefore you have to use shell: dpkg -l | grep python-apt.
read about the command module in the Ansible documentation:
It will not be processed through the shell, so .. operations like "<", ">", "|", and "&" will not work
As it recommends, use the shell module:
- name: Check if python-apt is installed
shell: dpkg -l | grep python-apt
register: python_apt_installed
ignore_errors: True
For what it's worth, you can check/confirm the installation in a debian environment using the apt command:
- name: ensure python-apt is installed
apt: name=python-apt state=present

rpm -q -> query only the descripton

I can query the informations about a rpm-package with
rpm -qi <rpm-package-name>
Example-Result of a Query:
tfaa004:/sm/bin # rpm -qi expect-5.45-16.1.3.i586
Name : expect
Version : 5.45
Release : 16.1.3
Architecture: i586
Install Date: Di 27 Jun 2017 15:31:08 CEST
Group : Development/Languages/Tcl
Size : 674166
License : SUSE-Public-Domain
Signature : RSA/SHA256, Do 25 Sep 2014 11:42:26 CEST, Key ID b88b2fd43dbdc284
Source RPM : expect-5.45-16.1.3.src.rpm
Build Date : Do 25 Sep 2014 11:42:16 CEST
Build Host : cloud120
Relocations : (not relocatable)
Packager : http://bugs.opensuse.org
Vendor : openSUSE
URL : http://expect.nist.gov
Summary : A Tool for Automating Interactive Programs
Description :
Expect is a tool primarily for automating interactive applications,
such as telnet, ftp, passwd, fsck, rlogin, tip, and more. Expect
really makes this stuff trivial. Expect is also useful for testing
these applications. It is described in many books, articles, papers,
and FAQs. There is an entire book on it available from O'Reilly.
Distribution: openSUSE 13.2
But I only want to query the Description. Is that possible?
The reason for that is that I want to process this information (the Description) in a C++ Program (I do this with popen()).
Maybe something like this:
rpm -qi -Description expect-5.45-16.1.3.i586
This is the correct sollution:
rpm -q --queryformat '%{DESCRIPTION}\n' expect-5.45-16.1.3.i586
[EDIT for openSUSE rpm output]:
rpm -qi package_name | sed '1,/Description/d;/Distribution/,$d'
This will only print lines between "Description" and "Distribution"
[The below cmds work for RHEL distros]
I do not believe the "rpm" utility has a flag to only print out the "Description" field, but it's as simple as using a pipe :)
You could do:
rpm -qi openssh-server-5.3p1-104.el6.x86_64 | awk '/Description/, 0'
Which will print every line after the pattern "Description" is found.
Or, if you're more inclined to use "grep":
rpm -qi openssh-server-5.3p1-104.el6.x86_64 | grep -A20 'Description'
the "-A n" flag tells grep to print n lines After the pattern is found.
***Edit: you may also use "sed":
rpm -qi openssh-server-5.3p1-104.el6.x86_64 | sed -e '1,/Description/ d'
Hope this helps.

Parsing CVS History Output

I just need to get a list of the most recent changes from CVS and parse them.
Example: The CVS user "Lollerskates" checked in a file with spaces. But spaces are the delimiter! And then "skates" checked in a file with a space in a folder name.
% cvs history -c -a -D 2011-03-14
A 2011-03-15 00:17 +0000 jschmoe 1.1 CoolCode.java Awesome/Source/Java/src/com/widgets/foo/ambiguous/abstraction == <remote>
M 2011-03-15 00:17 +0000 sumbody 1.2 MoreCoolCode.java Awesome/Source/Java/src/com/widgets/foo/ambiguous/abstraction == <remote>
A 2011-03-15 00:17 +0000 lollerskates 1.123 This File Name Has Spaces.html Awesome/Source/Java/src/com/widgets/foo/ambiguous/abstraction == <remote>
A 2011-03-15 00:17 +0000 jschmoe 1.1 MyAwesomeProject.java Awesome/Source/Java/src/com/widgets/foo/ambiguous/abstraction == <remote>
M 2011-03-15 00:17 +0000 skates 1.5 BlahBlah.java Awesome/Source/Java/src/com/widgets/foo/content/block type/cart == <remote>
What is a reliable way to parse this?
Alternatively, is there a different CVS command with more easily parsable results?
This regex captures all of these:
\w \d{4}-\d{2}-\d{2} \d{2}:\d{2} \+\d{4} (\w+)\s+(\d+.\d+)\s+([\w\s]+\.\w+)\s+([\w\s/]+)== \<remote\>
The user is in group #1, filename in group #3 and path in group #4.
In this very case probably cut is a better way? If the fields are fixed length...