How to send multiple stdin in ansible - automation

I have a bat file like this
#echo off
echo please enter Hostname(For Example 127.0.0.1 OR . OR PC-Name)
set /p ServerName="Server Name: "
echo "---------------------ServerName-----------------------------"
echo %ServerName%
echo "-------------------------------------------------"
cls
echo Please Select Authentication Mode:
echo 1- Windows Authentication
echo 2- SQL Server Authentication
set /p AuthMode="Please Enter 1 OR 2: "
I use "stdin" within Win_shell but it just gets one input and the AuthMode is always null
my ansible playbook.yml:
- name: Script
Win_shell: D:\Myscript.bat
args:
stdin: 127.0.0.1
is there any solution?

Try passing a multiline string:
- name: Script
Win_shell: D:\Myscript.bat
args:
stdin: |
127.0.0.1
2
You can check out https://yaml-multiline.info/ for an explanation of how to do multiline strings in yaml (and why the above | syntax means "keep newlines and have a single newline at the end").

Related

Pass arguments for SQL statement in a shell file from another shell file through ssh command

I am passing command line arguments to a shell file i.e assignRole.sh which contains an SQL command which will use these arguments like below
ssh -o StrictHostKeyChecking=no -T $key < /oracle/oracle_user/makhshif/./assignRole.sh name open_mode >> /oracle/oracle_user/dftest.txt
This gives me error and does not accept arguments of name and open_mode and gives error, but if I execute the statement outside of ssh command like:
/oracle/oracle_user/makhshif/./assignRole.sh name open_mode
This runs fine
What is the problem with ssh command and how should I adjust these parameters so these can be accepted for the shell script assignRole.sh
< /oracle/oracle_user/makhshif/./assignRole.sh
This commands sends a content of that file to stdin. So obviously it can't process variables that you haven't send to remote machine. Just preprocess your script or create a script on remote machine and call it with arguments
Though it's even easier to pass variables like this:
ssh -o StrictHostKeyChecking=no -T $key "var1=$var1 var2=$var2" < /oracle/oracle_user/makhshif/./assignRole.sh name open_mode >> /oracle/oracle_user/dftest.txt
For example my function for executing update scripts on all cluster nodes:
# functions:
ssh_exec(){
local DESCR="$1"; shift
local SCRIPT="$1"; shift
local hosts=("$#")
echo =================================================
echo = $DESCR
echo = Going to execute $SCRIPT...
read -a res -p "Enter 'skip' to skip this step or press Enter to execute: "
if [[ $res = "skip" ]]
then
echo Skipping $SCRIPT...
else
echo Executing $SCRIPT...
for host in "${hosts[#]}"
do
local cur=${!host}
echo Executing $SCRIPT on $host - $cur...
sshpass -p "$rootpass" ssh -o "StrictHostKeyChecking no" root#${cur} \
"ns1=$ns1 ns2=$ns2 search=$search zoo1=$zoo1 zoo2=$zoo2 zoo3=$zoo3 node0=$node0 pass=$pass CURIP=$cur CURHOST=$host bash -s" \
<$SCRIPT >log-$SCRIPT-$cur.log 2>&1
echo Done.
done
echo =================================================
fi
}
Then I use it like this:
read -p "Please check that Solr started successfully and Press [Enter] key to continue..."
#Solr configset and collections:
ssh_exec "Solr configset and collections" script06.sh zoo1 zoo2 zoo3
This command executes script06.sh on 3 servers (zoo1,zoo2,zoo3)
As Sayan said, using < redirects the output of running the assignRole.sh script locally, but you want to execute that script on the remote host, with the arguments.
Pass the whole command as the final argument to ssh, in quotes:
ssh -o StrictHostKeyChecking=no -T $key "/oracle/oracle_user/makhshif/./assignRole.sh name open_mode" >> /oracle/oracle_user/dftest.txt
or split into multiple lines for readability:
ssh -o StrictHostKeyChecking=no -T $key \
"/oracle/oracle_user/makhshif/./assignRole.sh name open_mode" \
>> /oracle/oracle_user/dftest.txt

Entrypoint script is not running from docker-compose file

My goal is to create an SQL login for my apps before running other images. Since my container uses Linux - scripts are saved with LF line endings. And the Docker output console is not showing any errors related to the script, only about my apps - they can't connect to the server because no such login exists.
The problem is that the shell script is not running and no login is being created. Thanks for your help in advance.
I was looking for the examples on the web, and here is what I came up with:
docker-compose.yml
version: '3.4'
services:
mssql:
image: mcr.microsoft.com/mssql/server:2019-latest
environment:
SA_PASSWORD: "3qqimIuTQEGqVCD!"
ACCEPT_EULA: "Y"
LOGIN: "MyLogin"
PASSWORD: "3qqimIuTQEGqVCD!"
ports:
- "1433:1433"
volumes:
- ./DockerScripts/SQL/CreateLogin.sql:/CreateLogin.sql
- ./DockerScripts/Shell/Entrypoint.sh:/Entrypoint.sh
entrypoint:
- ./Entrypoint.sh
webapi:
image: ${DOCKER_REGISTRY-}webapi
build:
context: .
dockerfile: Source/Code/Web/WebApi/Dockerfile
depends_on:
- mssql
maintenance:
image: ${DOCKER_REGISTRY-}maintenance
build:
context: .
dockerfile: Source/Code/Web/Maintenance/Dockerfile
depends_on:
- mssql
DockerScripts\Shell\Entrypoint.sh
#!/bin/bash
# Start SQL server
/opt/mssql/bin/sqlservr
# Wait for MSSQL server to start
export STATUS=1
i=0
while [[ $STATUS -ne 0 ]] && [[ $i -lt 30 ]]; do
i=$i+1
/opt/mssql-tools/bin/sqlcmd -t 1 -U sa -P $SA_PASSWORD -Q "select 1" >> /dev/null
STATUS=$?
done
if [ $STATUS -ne 0 ]; then
echo "Error: MS SQL Server took more than 30 seconds to start up."
exit 1
fi
echo "MS SQL Server started successfully."
echo "Setting up server login."
/opt/mssql-tools/bin/sqlcmd -U sa -P $SA_PASSWORD -S localhost -i CreateLogin.sql
DockerScripts\SQL\CreateLogin.sql
USE [master];
GO
CREATE LOGIN [$(LOGIN)] WITH PASSWORD=N'$(PASSWORD)', DEFAULT_DATABASE=[master], CHECK_EXPIRATION=OFF, CHECK_POLICY=OFF;
GO
ALTER SERVER ROLE [dbcreator] ADD MEMBER [$(LOGIN)];
GO
UPDATE
I removed a lot of stuff since it doesn't relate to the issue.
So for now, the main problem persists - Entrypoint.sh just not being called on compose startup.
Okay, so finally I was able to solve this issue.
The problem was not that Entrypoint.sh was not called, but that all the commands after
# Start SQL server
/opt/mssql/bin/sqlservr
were just skipped.
I don't really know why, but I was searching the web more and more and in the end, I came up with this solution.
First of all, I separated the login creation logic into its own script file, this slightly improves readability:
DockerScripts/Shell/CreateLogin.sh
#!bin/bash
echo "Creating MS SQL Login."
for i in {1..50};
do
/opt/mssql-tools/bin/sqlcmd -U sa -P $SA_PASSWORD -S localhost -i CreateLogin.sql
if [ $? -eq 0 ]
then
echo "MS SQL Login created."
break
else
echo "..."
sleep 1
fi
done
Secondly - I simplified my Entrypoint.sh file to just a few rows:
#!bin/bash
/opt/mssql/bin/sqlservr | /opt/mssql/bin/permissions_check.sh | /Scripts/CreateLogin.sh
Let me explain what the commands above means:
/opt/mssql/bin/sqlservr - this start the server itself.
/opt/mssql/bin/permissions_check.sh - this is just the default
entrypint file.
/Scripts/CreateLogin.sh - and this point us to the
server login creation.
And of course, I mounted the new shell script to a volume.
That's it, literally months of struggling with this issue, and turned out it was very simple to solve.
Hope this would help somebody else. Thanks!

String manipulation in .gitlab-ci variables

I'm trying to set up my ci file with some variables. I'm able to generate a variable like so;
...
variables:
TARGET_PROJECT_DIR: "${CI_PROJECT_NAME}.git"
However, I don't seem to be able to do this;
...
variables:
PROJECT_PROTOCOL_RELATIVE_URL: "${CI_PROJECT_URL//https:\/\/}.git"
If I run that in bash, I get the expected output which is gitlab.com/my/repo/url.git with the 'https://' removed and the '.git' appended.
My workaround has just been to export it in the 'script' section, but it feels a lot neater to add this to the variables section, since this is part of a template that is being inherited by the actual jobs. Is it possible?
There are several more useful variables defined in the GitLab CI environment.
CI_PROJECT_PATH gives you the <namespace>/<project name> (or just <project name> if you have no extra namespace) string and
CI_SERVER_HOST gives you the server name, so you could do
variables:
PROJECT_PROTOCOL_RELATIVE_URL: ${CI_SERVER_HOST}/${CI_PROJECT_PATH}.git
I have similar setups (also without quotes).
I'm not sure if that will work for you, since my runners and my server are under my control and I don't run pipelines with external projects.
But you can get all available variables displayed in the job log by running a job like this:
stages:
- env
show-env:
stage: env
script:
- env
Also always helpful is https://docs.gitlab.com/ee/ci/variables/predefined_variables.html
After looking around for similar challenges I found your not answered question. Here are my suggestions:
stages:
- todo
todo-job:
stage: todo
only:
- master
script:
#your question / example
- echo ${CI_PROJECT_URL}
- echo ${CI_PROJECT_URL:8:100}.git
#Because you have the word manipulation in the title, I have some more examples:
#Return substring between the two '_'
- INPUT="someletters_12345_moreleters.ext"
- SUBSTRING=`expr match "$INPUT" '.*_\([[:digit:]]*\)_.*' `
- echo $SUBSTRING
#Store a substring in a new variable and create an output
- b=${INPUT:12:5}
- echo $b
#Substring using grep with regex (more readable)
- your_number=$(echo "someletters_12345_moreleters.ext" | grep -E -o '[0-9]{5}')
- echo $your_number
#Substring using variable and 'grep' with regex (more readable)
- your_number=$(echo "$INPUT" | grep -E -o '[0-9]{5}')
- echo $your_number
#split a string and return a part using 'cut'
- your_id=$(echo "Release V14_TEST-42" | cut -d "_" -f2 )
- echo $your_id
#split the string of a variable and return a part using 'cut'
- VAR="Release V14_TEST-42"
- your_number=$(echo "$VAR" | cut -d "_" -f2 )
- echo $your_number
Gitlab output looks like:
$ echo ${CI_PROJECT_URL}
https://gitlab.com/XXXXXXXXXX/gitlab_related_projects/test
$ echo ${CI_PROJECT_URL:8:100}.git
gitlab.com/XXXXXXXXXX/gitlab_related_projects/test.git
$ INPUT="someletters_12345_moreleters.ext"
$ SUBSTRING=`expr match "$INPUT" '.*_\([[:digit:]]*\)_.*' `
$ echo $SUBSTRING
12345
$ b=${INPUT:12:5}
$ echo $b
12345
$ your_number=$(echo "someletters_12345_moreleters.ext" | grep -E -o '[0-9]{5}')
$ echo $your_number
12345
$ your_number=$(echo "$INPUT" | grep -E -o '[0-9]{5}')
$ echo $your_number
12345
$ your_number=$(echo "Release V14_TEST-42" | cut -d "_" -f2 )
$ echo $your_number
TEST-42
$ VAR="Release V14_TEST-42"
$ your_number=$(echo "$VAR" | cut -d "_" -f2 )
$ echo $your_number
TEST-42
Cleaning up project directory and file based variables
00:01
Job succeeded

Echo multi-line variable content over ssh

I'm trying to echo multiline variable over ssh, but the second line gets executed as a command.
msg="Hello World; Hello World2"; echo $msg; ssh -q newhost "echo "$msg""
Output:
Hello World; Hello World2
Hello World
bash: Hello: command not found
Is there a reason it needs to be a multi-line variable? why not send two distinct messages?
msg="Hello World"; msg2="Hello World2"; echo $msg; ssh -q localhost "echo "$msg""$msg2""
works fine
echo -e will let you interpret escaped characters like \n which you should use instead of semicolon ;

simulate nagios notifications

My normal method of testing the notification and escalation chain is to simulate a failure by causing one, for example blocking a port.
But this is thoroughly unsatisfying. I don't want down time recorded in nagios where there was none. I also don't want to wait.
Does anyone know a way to test a notification chain without causing the outage? For example something like this:
$ ./check_notifications_chain <service|host> <time down>
at <x> minutes notification email sent to group <people>
at <2x> minutes notification email sent to group <people>
at <3x> minutes escalated to group <management>
at <200x> rm -rf; shutdown -h now executed.
Extending this paradigm I might make the notification chain a nagios check in itself, but I'll stop here before my brain explodes.
Anyone?
If you only want to verify that the email alerts are working properly, you could create a simple test service, which generates a warning once a day.
test_alert.sh:
#!/bin/bash
date=`date -u +%H%M`
echo $date
echo "Nagios test script. Intentionally generates a warning daily."
if [[ "$date" -ge "1900" && "$date" -le "1920" ]] ; then
exit 1
else
exit 0
fi
commands.cfg:
define command{
command_name test_alert
command_line /bin/bash /usr/local/scripts/test_alert.sh
}
services.cfg:
define service {
host localhost
service_description Test Alert
check_command test_alert
use generic-service
}
This is an old post but maybe my solution can help someone.
I use the plugin "check_dummy" which is in the Nagios plugins pack.
As it says, it is stupid.
See some exemple of how it works :
Usage:
check_dummy <integer state> [optional text]
$ ./check_dummy 0
OK
$ ./check_dummy 2
CRITICAL
$ ./check_dummy 3 salut
UNKNOWN: salut
$ ./check_dummy 1 azerty
WARNING: azerty
$ echo $?
1
I create a file which contain the interger state and the optional text :
echo 0 OKAY | sudo tee /usr/local/nagios/libexec/dummy.txt
sudo chown nagios:nagios /usr/local/nagios/libexec/dummy.txt
With the command :
# Dummy check (notifications tests)
define command {
command_name my_check_dummy
command_line $USER1$/check_dummy $(cat /usr/local/nagios/libexec/dummy.txt)
}
Associated with the service description :
define service {
use generic-service
host_name localhost
service_description Dummy check
check_period 24x7
check_interval 1
max_check_attempts 1
retry_interval 1
notifications_enabled 1
notification_options w,u,c,r
notification_interval 0
notification_period 24x7
check_command my_check_dummy
}
So I just change the contents of the file "dummy.txt" to change the service state :
echo "2 Oups" | sudo tee /usr/local/nagios/libexec/dummy.txt
echo "1 AHHHH" | sudo tee /usr/local/nagios/libexec/dummy.txt
echo "0 Parfait !" | sudo tee /usr/local/nagios/libexec/dummy.txt
This allowed me to debug my notification program.
Hope it helps !