I have a bash script which checks for a paticular string and proceeds further but seems to be getting some error with binary operator expected
local artifacts=$(realpath artifacts)/middle-end
local env
local account_id=${1}
local branch_name=${2}
local user_environments=${3}
local gitlab_user_id=${4}
env=$(ci/scripts/get-details-env.py -m "${user_environments}" -u "${user_id}")
# Deploy to int1 from develop
echo "$branch_name"
if [ "${branch_name}" == "develop" ]; then
env=brt-int;
fi
if [ "${branch_name}" =~ ^brt-rc-.* ]; then
env=brt-uat;
fi
mkdir -p ${artifacts}
cd middle-end
ln -s ${NODE_PATH} ./node_modules
npm run build
I know what your problem is, you must be using the new test operator [[. [http://mywiki.wooledge.org/BashFAQ/031][bash new test details]
if [[ "${branch_name}" =~ ^atf-rc-.* ]]; then
env=atf-stage1;
fi
Related
Context
I've written a Bash script that automatically deletes a repo from a GitLab server, and that creates a new GitLab repo.
Code
The code that deletes the repository is:
delete_existing_repository() {
local repo_name="$1"
local repo_username="$2"
# load personal_access_token
local personal_access_token
personal_access_token=$(echo "$GITLAB_PERSONAL_ACCESS_TOKEN_GLOBAL" | tr -d '\r')
local output
output=$(curl --silent -H 'Content-Type: application/json' -H "Private-Token: $personal_access_token" -X DELETE "$GITLAB_SERVER_HTTP_URL"/api/v4/projects/"$repo_username"%2F"$repo_name")
if [ "$(lines_contain_string '{"message":"404 Project Not Found"}' "${output}")" == "FOUND" ]; then
echo "ERROR, you tried to delete a GitLab repository that does not exist."
exit 183
fi
}
and the function that checks whether GitLab processed the repo push succesfully, is:
# Create repository.
curl --silent -H "Content-Type:application/json" "$GITLAB_SERVER_HTTP_URL/api/v4/projects?private_token=$personal_access_token" -d "{ \"name\": \"$gitlab_repo_name\" }" > /dev/null 2>&1 &
sleep 30
printf "\n Waiting 30 secs untill repo is (re)created in GitLab server."
Question
The issue is that I am experiencing some difficulties in determining when the GitLab repository is deleted successfully, and when it is created and processed successfully. Right now, I just "brute-force" wait 30 seconds, because so far, my system has been fast enough to do it within that time. However, that is inefficient, and unreliable because it should also work on slower systems. Hence I would like to ask:
How can I delete and create a GitLab repository in Bash, such that at the end of the command, the repo is completely deleted and (re)created successfully?
Partial answer: a fully created GitLab repo will be clonable. To test whether creation has completed, try to clone the repo. This can only succeed if the repo is fully created, and it will be fast since you're trying to clone an empty repo.
I don't have a suggestion for validating the deletion, though, because failure to clone would not confirm deletion is complete, although failure to create might indicate it's not.
However, if at the end of your bash script the clone yields an empty repo as expected, you know for sure that the delete + recreate operation was successful as a whole.
Description
To ensure the bash code waits until a repository is created or deleted successfully in GitLab, I wrote a method that returns FOUND if the repository exists within the GitLab server, and NOTFOUND if it does not exist. Next I wrote two methods that check n times whether the repository does/does not exist, with 5 second pauses in between:
Solution
# run with:
# bash -c 'source src/import.sh && wait_until_repo_exists_in_gitlab nonexistant_repo'
# bash -c 'source src/import.sh && wait_until_repo_exists_in_gitlab sponsor_example'
wait_until_repo_exists_in_gitlab(){
local gitlab_repo_name="$1"
# Specify how many retries are allowed.
local nr_of_retries=10
local termination_limit="$((nr_of_retries-2))"
local i="0"
while [ $i -lt $nr_of_retries ]; do
local found_repo="$(repo_exists_in_gitlab_server "$gitlab_repo_name")"
i=$[$i+1]
if [ "$found_repo" == "FOUND" ]; then
break
elif [[ "$i" == "$termination_limit" ]]; then
echo "Error, did not find repo in GitLab server, within permitted timeframe."
exit 6
break
fi
sleep 5
done
}
# bash -c 'source src/import.sh && wait_until_repo_does_not_exist_in_gitlab nonexistant_repo'
# bash -c 'source src/import.sh && wait_until_repo_does_not_exist_in_gitlab sponsor_example'
wait_until_repo_does_not_exist_in_gitlab(){
local gitlab_repo_name="$1"
# Specify how many retries are allowed.
local nr_of_retries=10
local termination_limit="$((nr_of_retries-2))"
local i="0"
while [ $i -lt $nr_of_retries ]; do
local found_repo="$(repo_exists_in_gitlab_server "$gitlab_repo_name")"
i=$[$i+1]
if [ "$found_repo" == "NOTFOUND" ]; then
break
elif [[ "$i" == "$termination_limit" ]]; then
echo "Error, still found the repo in GitLab server, within permitted timeframe."
exit 6
break
fi
sleep 5
done
}
# run with:
# bash -c 'source src/import.sh && repo_exists_in_gitlab_server nonexistant_repo'
# bash -c 'source src/import.sh && repo_exists_in_gitlab_server sponsor_example'
repo_exists_in_gitlab_server(){
local gitlab_repo_name="$1"
local temporary_test_filepath=/tmp/TESTRET
local expected_if_non_existant="fatal: repository '$GITLAB_SERVER_HTTP_URL/$GITLAB_SERVER_ACCOUNT_GLOBAL/$gitlab_repo_name/' not found"
local acceptable_warning="warning: redirecting to $GITLAB_SERVER_HTTP_URL/$GITLAB_SERVER_ACCOUNT_GLOBAL/$gitlab_repo_name.git/"
# Delete file exists.
delete_file_if_it_exists $temporary_test_filepath
# Check if gitlab repo exists and output any errors to file.
something=$(git ls-remote http://$GITLAB_SERVER_ACCOUNT_GLOBAL:$GITLAB_PERSONAL_ACCESS_TOKEN_GLOBAL#$GITLAB_SERVER/$GITLAB_SERVER_ACCOUNT_GLOBAL/$gitlab_repo_name 2> $temporary_test_filepath)
# Used to verify it throws an error if auth is invalid.
#something=$(git ls-remote http://$GITLAB_SERVER_ACCOUNT_GLOBAL:$GITLAB_PERSONAL_ACCESS_TOKEN_GLOBALasdf#$GITLAB_SERVER/$GITLAB_SERVER_ACCOUNT_GLOBAL/$gitlab_repo_name 2> $temporary_test_filepath)
# Check if the output file contains an error.
if [[ -n `cat $temporary_test_filepath` ]]; then
# Check if the error indicates the repo does not exist, or whether there is another issue.
if [ "$(file_contains_string "$expected_if_non_existant" "$temporary_test_filepath")" != "FOUND" ]; then
# An error is thrown, check if it is an acceptable error or not.
if [ "$acceptable_warning" == "$(cat $temporary_test_filepath)" ]; then
# This means the repository exists.
echo "FOUND"
else
echo 'ERROR, checking if GitLab repo exists yielded an error other than "the repo does not exist"'
echo "$(cat $temporary_test_filepath)."
echo "$acceptable_warning."
exit 5
fi
elif [ "$(file_contains_string "$expected_if_non_existant" "$temporary_test_filepath")" == "FOUND" ]; then
# The output file contained the expected error, for when a repo does not exist.
echo "NOTFOUND"
else
echo "Error, checking if a GitLab repo exists in server, yielded an unexpected output error:"
echo "$(cat $temporary_test_filepath)."
fi
else
echo "FOUND"
fi
# Delete file exists.
delete_file_if_it_exists $temporary_test_filepath
}
Usage
Code that creates a GitLab repository and waits until it is created:
# Create repository.
curl --silent -H "Content-Type:application/json" "$GITLAB_SERVER_HTTP_URL/api/v4/projects?private_token=$personal_access_token" -d "{ \"name\": \"$gitlab_repo_name\" }" > /dev/null 2>&1 &
wait_until_repo_exists_in_gitlab "$gitlab_repo_name"
Code that deletes a repo and waits until it is deleted:
#######################################
# Checks if repository exists in the GitLab server and deletes it. Otherwise, an
# error is shown.
# How to run:
# source src/import.sh src/helper/GitLab/helper_gitlab_modify.sh && delete_existing_repository_from_gitlab
# "sponsor_example" "root"
# Local variables:
# gitlab_repo_name
# gitlab_username
# personal_access_token
# Globals:
# GITLAB_PERSONAL_ACCESS_TOKEN_GLOBAL
# GITLAB_SERVER_HTTP_URL
# Arguments:
# Name of the GitLab repository.
# The GitLab username.
# Returns:
# 0 if funciton was evaluated succesfull.
# 183 if an attempt was made to delete a GitLab repository that did not exist.
# Outputs:
# None.
#######################################
# run with:
# bash -c 'source src/import.sh src/helper/GitLab/helper_gitlab_modify.sh && delete_existing_repository_from_gitlab new_repo root'
delete_existing_repository_from_gitlab() {
local repo_name="$1"
local repo_username="$2"
# load personal_access_token
local personal_access_token
personal_access_token=$(echo "$GITLAB_PERSONAL_ACCESS_TOKEN_GLOBAL" | tr -d '\r')
local output
output=$(curl --silent -H 'Content-Type: application/json' -H "Private-Token: $personal_access_token" -X DELETE "$GITLAB_SERVER_HTTP_URL"/api/v4/projects/"$repo_username"%2F"$repo_name")
if [ "$(lines_contain_string '{"message":"404 Project Not Found"}' "${output}")" == "FOUND" ]; then
echo "ERROR, you tried to delete a GitLab repository that does not exist."
exit 183
fi
wait_until_repo_does_not_exist_in_gitlab "$gitlab_repo_name"
}
I have Pipeline job in Jenkins and there is a step that executes this bash script:
sh """
$ANDROID_HOME/platform-tools/adb pull /sdcard/Pictures/screenshots
if [ "$DEFAULT_LOCALE" = "en" ]
then
DEFAULT_LOCALE="en-US"
fi
if [ "${env.UPDATE_BASE}" == "true" ] || [ ! -d "${env.CACHE_HOME}/${env.BRANCH}" ]; then
if [ ! -d "${env.CACHE_HOME}/${env.BRANCH}" ]; then
mkdir -p ${env.CACHE_HOME}/${env.BRANCH}
fi
for imgfile in screenshots/*.png; do
if [[ $imgfile == *"_${env.DEFAULT_LOCALE}-"*.png ]]; then
cp -rf screenshots/$imgfile ${env.CACHE_HOME}/${env.BRANCH}
fi
done
else
rm -f screenshots/*_${env.DEFAULT_LOCALE}-*.png
cp -rf ${env.CACHE_HOME}/${env.BRANCH}/* screenshots
fi
"""
However, when the pipeline reaches this step, it fails with this error:
groovy.lang.MissingPropertyException: No such property: imgfile for class: groovy.lang.Binding
What is wrong in the script?
If all your variables are shell variables then you should use triple single quotes.
If you have a mix of shell and Groovy variables (or only Groovy ones) then you should use triple double quotes.
In order to defer the evaluation of the shell variables in the latter case, you need to escape their dollar signs using one of these forms (I'm not sure which):
if [[ \$imgfile == *"_${env.DEFAULT_LOCALE}-"*.png ]]; then
or
if [[ \\$imgfile == *"_${env.DEFAULT_LOCALE}-"*.png ]]; then
or
if [[ ${'$'}imgfile == *"_${env.DEFAULT_LOCALE}-"*.png ]]; then
I want to jail an "normal" user with the special group developer for SFTP and SSH.
The user can only navigate in /srv/DEVELOPMENT (SSH/SFTP) AND over SSH, the user can only execute a limit of commands (see the script at the bottom).
Why i want this?
I work on a little project. Last days, another developers wan't to support the project with their experiences. The developer can be edit the "developer-website" and can start/stop/restart an Node.js application over SSH. The next think is: The user must use the shell to change their account password.
Currently, i have configured the SSH-Deamon with following steps:
Jail over SFTP
Match Group developer
X11Forwarding no
AllowTcpForwarding yes
ChrootDirectory /srv/DEVELOPMENT
ForceCommand internal-sftp
The user was added by following commands/options:
useradd --base-dir /srv/ --home-dir /srv/ --no-user-group --shell /srv/shell.sh $USERNAME
usermod -G developer $USERNAME
id $USERNAME
passwd $USERNAME
Current Directory Permissions
/srv developer:root 0755
/srv/DEVELOPMENT developer:root 0750
/srv/DEVELOPMENT/* developer:root 0777
With SFTP it work's correctly. The second part to jail the user over SSH is currently little bit harder. This step won't work currently, and thats is my question.
The chroot is limited on internal-sfpt. When i try to login, the connection will be aborted with the message, that the connection is only allowed for sftp:
ssh TestUser#example.com
TestUser#example.com's password:
This service allows sftp connections only.
Connection to example.com closed.
Here, i had remove ForceCommand on the SSH-Deamon config > The Login will be succeed.
But here is my problem
When i try to login, no executables cant be used:
ssh TestUser#example.com
TestUser#example.com's password:
Linux example.com 4.9.0-3-amd64 #1 SMP Debian 4.9.30-2+deb9u2 (2017-06-26) x86_64
Last login: Sun Jul 30 18:00:11 2017 from ****************
/srv/shell.sh: No such file or directory
Connection to example.com closed.
/srv/shell.sh is a custom shell-script to limit the commands, for sample:
#!/bin/bash
commands=("man" "passwd" "ls" "account", "whoami", "clear", "cd")
RED='\033[0;31m'
YELLOW='\033[0;33m'
MAGENTA='\033[0;35m'
CYAN='\033[0;36m'
NC='\033[0m' # No Color
INDENTATION=' '
SYSTEM_UPTIME=`uptime --pretty`
SYSTEM_USERS=`who -q`
SYSTEM_QUOTA="None"
SYSTEM_RAM="None"
timestamp(){
date +"%Y-%m-%d %H:%M:%S"
}
log(){
echo -e "[$(timestamp)]\t$1\t$(whoami)\t$2" >> /var/log/developer-user/shell.log;
}
execute() {
# EXIT
if [[ "$ln" == "exit" ]] || [[ "$ln" == "q" ]]
then
exit
# HELP
elif [[ "$ln" == "help" ]]
then
echo "Type exit or q to quit."
echo "Commands you can use:"
echo " account"
echo " help"
echo " echo"
echo " man <ManPage>"
echo " passwd"
echo " ls"
echo " clear"
echo " cd"
# CD
elif [[ "$ln" =~ ^cd\ .*$ ]]
then
LAST=`pwd`
$ln
CURRENT=`pwd`
if [[ $CURRENT == "/srv" ]]
then
log CHANGE_DIR FAILED_PERMISSIONS "$ln"
echo -e "${RED}ERROR:${NC} Sorry, you can't change to the previous directory ${YELLOW}\"${CURRENT}\"${NC}."
cd $LAST
elif [[ ! "$CURRENT" =~ ^/srv/DEVELOPMENT ]]
then
log CHANGE_DIR FAILED_PERMISSIONS "$ln"
echo -e "${RED}ERROR:${NC} Sorry, you can't change to the directory ${YELLOW}\"${CURRENT}\"${NC}."
cd $LAST
elif [[ `stat -c "%G" ${CURRENT}` == "friendlounge" ]]
then
log CHANGE_DIR "$ln"
else
log CHANGE_DIR FAILED_PERMISSIONS "$ln"
echo -e "${RED}ERROR:${NC} You have no permissions on ${YELLOW}\"${CURRENT}\"${NC}."
cd $LAST
fi
# ECHO
elif [[ "$ln" =~ ^echo\ .*$ ]]
then
$ln
log COMMAND "$ln"
# ACCOUNT
elif [[ "$ln" = "account" ]]
then
echo -e "YOUR ACCOUNT:"
echo -e "Username: $(whoami)"
# OTHERS
else
ok=false
for cmd in "${commands[#]}"
do
if [[ "$cmd" == "$ln" ]]
then
ok=true
fi
done
if $ok
then
$ln
else
echo -e "${RED}ERROR:${NC} You have no permissions to execute ${YELLOW}\"${ln}\"${NC}."
log DENIED "$ln"
fi
fi
}
# WELCOME MESSAGE
echo -e "${INDENTATION}${MAGENTA}Account:${NC}${INDENTATION}$(whoami)"
echo -e "${INDENTATION}${MAGENTA}Date:${NC}${INDENTATION}${INDENTATION}$(timestamp)"
echo -e "${INDENTATION}${MAGENTA}Uptime:${NC}${INDENTATION}${INDENTATION}${SYSTEM_UPTIME}"
echo -e "${INDENTATION}${MAGENTA}Users:${NC}${INDENTATION}${INDENTATION}${SYSTEM_USERS}"
echo -e "${INDENTATION}${MAGENTA}Quota:${NC}${INDENTATION}${INDENTATION}${SYSTEM_QUOTA}"
echo -e "${INDENTATION}${MAGENTA}RAM:${NC}${INDENTATION}${INDENTATION}${SYSTEM_RAM}"
log LOGIN "$#"
cd
trap "trap=\"\";log LOGOUT;exit" EXIT
# Optionally check for '-c custom_command' arguments passed directly to shell
# Then you can also use ssh user#host custom_command, which will execute /root/rbash.sh
if [[ "$1" == "-c" ]]
then
shift
execute "$#"
else
while echo -e -n "${RED}$(whoami)${YELLOW}#${CYAN}$(hostname) ${YELLOW}$(pwd) ${MAGENTA}#${NC} " && read ln
do
execute "$ln"
done
fi
This shell-script checks the permission of the user and force only to the /srv/DEVELOPMENT directory or subdirectorys.
It's irrelevant to set another login-shells like /bin/bash or other - On each login, the SSH-Demon close the connection after the error message XXXX: No such file or directory.
I had try to set different permissions and other. i can't resolve the problem to connect over ssh.
Anyone have an idea?
Before you answer
yes, i known the possible security reasons (for sample, to manage the permissions over my "own" shell-login-script)
no, i don't want to install huge alternatives like schroot or jailkit (found on google, reading the first minutes says, that these alternatives uses a completely decoupled system like a virtual-machine(?) - inform me, when it's wrong with explicit informations)
You may try this, It's is very easy to use.
you can jail a user in 3 steps.
add user
create a jail with a simple configuration file.
jail this user.
The tool is located at :https://github.com/pymumu/jail-shell
So I have a script in my .bashrc for customizing my prompt (see below).
function git_unpushed {
brinfo=$(git branch -v)
if [[ $brinfo =~ ("[ahead "([[:digit:]]*)]) ]]
then
echo "Not Pushed: ${BASH_REMATCH[2]}"
fi
}
function git_untracked {
untracked=$(git clean --dry-run | wc -l)
if [ $untracked -gt 0 ]
then
echo "Untracked: "$untracked
fi
}
export PS1="\
$(
# last_result=$?
uid="$(id -u)"
host="\[\e[97m\]\H"
path="\[\e[94m\]\w"
# If root
if [ "$uid" = "0" ];
then
user="\[\e[95m\]\u"
symbol="\[\e[97m\]#"
else
# If not root
user="\[\e[96m\]\u"
symbol="\[\e[97m\]\$"
fi
# If Git Repo
if [ -d './.git' ];
then
unpushed=$(git_unpushed)
untracked=$(git_untracked)
branch=$(__git_ps1)
status=$(git diff --shortstat)
second_line="hi"
else
second_line=$path
fi
echo "\[\e[1m\]$user#$host\n$second_line\n$symbol: \[\e[0m\]"
)"
My Question: Why does the path not get replaced whenever I cd to a git repo? (it does if I start a bash prompt within the repo"
I am using Ubuntu 14.04
Update:
After lot of work getting it just right, he is my result: Custom $PS1
Thanks everyone who helped out!
Edit:
As #EtanReisner points out, your code should work as intended for all users by enclosing your command substitution in single quotes.
export PS1='\
$(
# last_result=$?
uid="$(id -u)"
host="\[\e[97m\]\H"
path="\[\e[94m\]\w"
# If root
if [ "$uid" = "0" ];
then
user="\[\e[95m\]\u"
symbol="\[\e[97m\]#"
else
# If not root
user="\[\e[96m\]\u"
symbol="\[\e[97m\]\$"
fi
# If Git Repo
if [ -d "./.git" ];
then
unpushed=$(git_unpushed)
untracked=$(git_untracked)
branch=$(__git_ps1)
status=$(git diff --shortstat)
second_line="hi"
else
second_line=$path
fi
echo "\[\e[1m\]$user#$host\n$second_line\n$symbol: \[\e[0m\]"
)'
Old Answer:
This is because what you want to happen is only running every time your ~/.bashrc gets sourced. To get it to run after every command you execute, you can create a function and set the environment variable PROMPT_COMMAND to that function.
Try this:
new_ps1 (){
export PS1="\
$(
# last_result=$?
uid="$(id -u)"
host="\[\e[97m\]\H"
path="\[\e[94m\]\w"
# If root
if [ "$uid" = "0" ];
then
user="\[\e[95m\]\u"
symbol="\[\e[97m\]#"
else
# If not root
user="\[\e[96m\]\u"
symbol="\[\e[97m\]\$"
fi
# If Git Repo
if [ -d './.git' ];
then
unpushed=$(git_unpushed)
untracked=$(git_untracked)
branch=$(__git_ps1)
status=$(git diff --shortstat)
second_line="hi"
else
second_line=$path
fi
echo "\[\e[1m\]$user#$host\n$second_line\n$symbol: \[\e[0m\]"
)"
}
PROMPT_COMMAND="new_ps1"
We have code to check for a node install:
which="type -p"
if [ $SHELL = "/bin/zsh" ]; then
which="whence"
fi
# make sure that node exists
node=`$which node 2>&1`
ret=$?
if [ $ret -ne 0 ] || ! [ -x "$node" ]; then
<"This error code is returned">
But when I run this with ZSH (OhMyZsh) it returns a 127 (does not exist). Commenting out the which="whence" lets it run fine.
Without removing the whole aliasing bit is there any way to have ZSH play along with this? Ideally I'd like to make a change on my end to make this work rather than modifying this code at all.
You mean, you run $node and it appears that you’ve tried to run command whose name is node --alias-args which does not exist?
If this is true, change the third line to use whence -p: it has the same output as type -p in bash. If not, please, explain when this code is returned.
Update: I do not know what was done in ohmyzsh (though I have not a single idea how to make a builtin not found) so just try to rewrite the code in this way:
# At the very top
if [ -n $ZSH_VERSION ] ; then
emulate -L zsh
endif
<...>
which="type -p"
if [ -n $ZSH_VERSION ] ; then
which=( whence -p ) # Changes variable type as well
endif
node=`$which node 2>&1`
if (( ? )) || ! test -x $node ; then
<...>