Command working at the command line but not in script - linux

I have a shell script that I'm running that is not quite working as expected. When it is run manually at the command line, it works perfectly and does everything I expect. Once it is put into a script, the results disappear.
Here is what I'm running:
result=`/bin/echo "$query" | /usr/local/bin/tsql -S $server -p $port -U $user -P $pass -o fhq 2> output`
The case where the login fails and errors are written to output works perfectly in the script, but when the login is successful and results are returned, nothing is set to result.
Any help will be appreciated, thanks.

Please, try it as mentioned below :
result=/bin/echo "$query" | /usr/local/bin/tsql -S $server -p $port -U $user -P $pass -o fhq 2> output 1> success

Related

Error when stacking SSH command arguments within a bash script using other scripts as variables

I have a csv file called addresses.csv which looks like this,
node-1,xx.xxx.xx.xx,us-central-a
....
node-9,xxx.xx.xxx.xx,us-east1-a
I have a script below called 0run.sh,
#!/bin/bash
username='user'
persist="bash /home/${username}/Documents/scripts/disk/persistentDisk.sh"
first="bash /home/${username}/Documents/scripts/disk/firstAttach.sh"
while IFS=, read -r int ip <&3; do
if [ "$int" == "node-1" ]; then
--->ssh -i ~/.ssh/key -o StrictHostKeyChecking=no -l ${username} ${ip} "${persist}; ${first}"<---
else
ssh -i ~/.ssh/key -o StrictHostKeyChecking=no -l ${username} ${ip} "${first}"
fi
done 3<addresses.csv
The error occurs in the part of the code where I drew the arrows.
When it runs on node-1, instead of running ..persistentDisk.sh followed by ..firstAttach.sh, it only runs ..persistentDisk.sh and gives me the following error before it runs ..persistentDisk.
bash: /home/user/Documents/scripts/disk/firstAttach.sh: No such file or directory
The rest of the script runs completely fine. The only error occurs at this one part where it misses the 2nd script.
When I run the command like this it runs fine.
ssh -i ~/.ssh/key -o StrictHostKeyChecking=no -l ${username} ${ext} "${first}"
When I run it like this, it runs fine as well.
ssh -i ~/.ssh/key -o StrictHostKeyChecking=no -l user xxx.xx.xxx.xx "bash /home/${username}/Documents/scripts/disk/persistentDisk.sh; bash /home/${username}/Documents/scripts/disk/firstAttach.sh"
When I run the command like with a \ before the ; to escape it like this,
ssh -i ~/.ssh/key -o StrictHostKeyChecking=no -l ${username} ${ext} "${persist}\; ${first}"
I get the following error, and neither scripts run within the node-1 part of the code, but the rest of the code's else loops run fine.
bash: /home/user/Documents/scripts/disk/persistentDisk.sh;: No such file or directory
Why can't I stack the 2 commands within the if statement in the ssh using variables?
If I clearly understand: your real problem consist to leave STDIN free for interaction in target host!
About read and redirection
Try using:
#!/bin/bash
username='user'
persist="bash /home/${username}/Documents/scripts/disk/persistentDisk.sh"
first="bash /home/${username}/Documents/scripts/disk/firstAttach.sh"
while IFS=, read -r -u $list int ip foo; do
if [ "$int" == "node-1" ]; then
echo CMD... $ip, $persist
else
[ "$ip" ] && echo CMD... $ip, $first
fi
done {list}<addresses.csv
Tested, this èroduce:
CMD... xx.xxx.xx.xx, bash /home/user/Documents/scripts/disk/persistentDisk.sh
CMD... xxx.xx.xxx.xx, bash /home/user/Documents/scripts/disk/firstAttach.sh
-u flag to read, tell to use file descriptor ${list} instead of STDIN
foo is some useless variable used to prevent rest of line to be stored in $ip (xx.xxx.xx.xx,us-central-a in this case)
{list}</path/to/filename create a new variable by finding any free file descriptor.
About ssh (and redirection)
You could use:
#!/bin/bash
username='user'
persist="/home/${username}/Documents/scripts/disk/persistentDisk.sh"
first="/home/${username}/Documents/scripts/disk/firstAttach.sh"
while IFS=, read -r -u $list int ip foo; do
[ "$int" = "node-1" ] && cmd=persist || cmd=first
[ "$ip" ] && ssh -i ~/.ssh/key -t -o StrictHostKeyChecking=no \
-l ${username} ${ext} /bin/bash "${!cmd}"
done {list}<addresses.csv
By using this syntax, you will keep STDIN free for script running on target host.

Using Variable in Shell script as input for another command

#!/bin/bash
sudo docker-compose -f /home/administrator/compose/docker-compose.yml up --build -d
OUTPUT=$(docker ps | grep 'nginx_custom' | awk '{ print $1 }')
echo $OUTPUT
sudo docker $OUTPUT nginx -s reload
This the the ID that get´s printed correctly in the console.
6e3b3aa3fbc4
This command works fine.
docker exec 6e3b3aa3fbc4 nginx -s reload
However the variable seems not to get passed to the command here:
sudo docker $OUTPUT nginx -s reload
I am quite unfamiliar with the shell :(. How do I pass the variable to a command that is longer than just echo?
add set -x to the script and see what happens:
you can probably get rid of grep and incorporate it inside awk
#!/bin/bash
set -x
sudo docker-compose -f /home/administrator/compose/docker-compose.yml up --build -d
OUTPUT=$(docker ps | awk '/ngnix_custom/{ print $1 }')
echo $OUTPUT
sudo docker $OUTPUT nginx -s reload

BCP Command on Shell (.sh file)

I have a .sh script that do this:
bcp "EXEC SPName" queryout "test.csv" -k -w -t"," -S "$server" -U "$user" -P "$pass"
The variables $server, $user and $pass are being read from a external config file.
The problem is that the variables don't work and give me always connection timeout. For example if I use the same command but with the variables hard coded works fine:
bcp "EXEC SPName" queryout "test.csv" -k -w -t"," -S "TEST" -U "admin" -P "admin"
How I can make the command dynamic?
I found the problem, I was reading the variables from a external json file created in Windows and the file contained "\r" at the end and then the command could not execute.
How I solved:
sed -i 's/\r//g' YourFile.json

Shell script: execute 2 commands and keep first running

I'm trying to write a shell script for my docker image where:
a mssqql server is started
database setup happens
However with my current script my sql server instance stops as soon as the data import is done. Could anyone point me out what I'm doing wrong?
#!/bin/bash
database=myDB
wait_time=30s
password=myPw
exec /opt/mssql/bin/sqlservr &
echo importing data will start in $wait_time...
sleep $wait_time
echo importing data...
/opt/mssql-tools/bin/sqlcmd -S 0.0.0.0 -U sa -P $password -i ./init.sql
for entry in "table/*.sql"
do
echo executing $entry
/opt/mssql-tools/bin/sqlcmd -S 0.0.0.0 -U sa -P $password -i $entry
done
for entry in "data/*.csv"
do
shortname=$(echo $entry | cut -f 1 -d '.' | cut -f 2 -d '/')
tableName=$database.dbo.$shortname
echo importing $tableName from $entry
/opt/mssql-tools/bin/bcp $tableName in $entry -c -t',' -F 2 -S 0.0.0.0 -U sa -P $password
done
I did not see any clear mistakes in your shell script. I am just advising you the below:-
Try to run the server from the current shell of the script without exec
/opt/mssql/bin/sqlservr &
Put some echo in both the loop statements to check what is going on there.
Hope this will help.
Seems I need to add set -m to resolve this.

Why doesn't the login command accept piped stdin?

While
echo pwd | bash -i
works
echo pwd | login -f root
doesn't work. I expected the login command to set some environment variables and start an interactive shell, but apparently it is somehow special.
What does the login command do so the example above doesn't work? And are there any alternatives to the login command which can be used in that way?
The login command checks if it is connected to a tty before working. You can simulate a tty with the script command as answered here https://stackoverflow.com/a/1402389/3235192
echo pwd | script -qc "login -f root" /dev/null
Also works with heredoc.
script -qc "login -f root" /dev/null << EOF
pwd
EOF

Resources