How to pass an argument to Plink in VBA - vba

I am trying the following string in command prompt to execute some (test) remote commands on my server:
plink.exe -ssh -pw [PASSWD] [U/NAME]#[SERVER] -m cmds.bat -v
In my cmds.bat file I have some test commands:
sleep 3
#echo off
ls -la ~/
#echo on
sleep 1
I now want to beef this up to run a remote script while passing an argument. The argument will be handled and appended by my VBA code. This is the part I am stuck at. Please note the following VBA code is only a snippet; the part that calls Plink. The surrounding code, I am happy with:
If re.Test(Msg.Subject) Then
Set matchCol = re.Execute(Msg.Subject)
For Each match In matchCol
shellStr = "plink.exe -ssh [USERNAME]#[SERVER] -pw [P/WORD] -m cmds.bat " & match
Shell(shellStr, vbNormalFocus)
Next
End If
The offending line is:
shellStr = "plink.exe -ssh [USERNAME]#[SERVER] -pw [P/WORD] -m cmds.bat " & match
I do not know how to append the value held in variable match (captured by the Regexp) to the string to be executed in opening the shell.
The bat file will handle the command for actually running the script on the remote Unix server, where instead of ls -la ~/ in the above example I will use:
python ~/myscript.py [ARGUMENT FROM VBA VARIABLE "match"]
But how do I pass this match variable's value into this?

you cannot do this; plink just doesn't support this usage. your best bet is doing what you suggested in your comment: build the script on the fly. (and maybe don't call it .bat, that seems misleading a bit …)

Related

Running sqlcmd in batch file works but running the same batch file as a scheduled task works and does nothing

I have looked at many SO questions/answers and though some seem similar to my issue they do not seem to be. The answers given fix issues the questions were asking about but will not solve my issue.
I have a batch file...
#ECHO ON
ECHO Disabling the following... >> C:\App\Debug.log
ECHO - V1 >> C:\Apps\Debug.log
FOR /F "tokens=* USEBACKQ" %%F IN (`sqlcmd -j -S DOMAIN\SQLSERVER -U username -P password -d DBNAME -Q "UPDATE [DBNAME].[dbo].[table1] SET ColOne='V1_OFF' WHERE ColOne='V1'"`) DO (
Echo %%F >> C:\Apps\Debug.log
)
EXIT /B
When I run this file at the command prompt it works perfectly fine. When I run it as a scheduled task it show me the echos but nothing for the for loop as expected.
Yes I have made sure the username (using whoami) is the same for the scheduled task set up as the manual run that I do.
Yes I know the user running the script has rights to everything (file access as well as DB access) because it works fine running it from the command prompt.
Scheduled task is set to run wither user is logged on or not.
Any ideas what might be wrong or what I can try for debugging purposes?
Thanks!
sqlcmd is perhaps not enough. cmd.exe in environment of scheduled task may fail to find the executable using local PATHEXT and local PATH environment variables. The executable should be specified with full qualified file name, i.e. drive + path + name + extension. Then the batch file does not anymore depend on the environment variables PATH and PATHEXT because of all files are referenced with full qualified file name.
for executes the specified command line with starting in background one more command process with %ComSpec% /c and the specified command line appended. This means executed is following with Windows installed on drive C::
C:\Windows\System32\cmd.exe /c sqlcmd -j -S DOMAIN\SQLSERVER -U username -P password -d DBNAME -Q "UPDATE [DBNAME].[dbo].[table1] SET ColOne='V1_OFF' WHERE ColOne='V1'"
for captures everything written to handle STDOUT of started command process. The lines of captured output are processed line by line by for after started cmd.exe terminated itself. Error messages output by started cmd.exe or the commands/executables executed by Windows command processor in background to handle STDERR are redirected to handle STDERR of command process processing the batch file and printed to console. But there is no console window on running a batch file as scheduled task. So error messages cannot be seen in this case.
The for command line can be modified easily here to get also error messages written into the C:\Apps\Debug.log.
FOR /F "tokens=* USEBACKQ" %%F IN (`sqlcmd -j -S DOMAIN\SQLSERVER -U username -P password -d DBNAME -Q "UPDATE [DBNAME].[dbo].[table1] SET ColOne='V1_OFF' WHERE ColOne='V1' 2^>^&1"`) DO (
The Microsoft article Using command redirection operators explains 2>&1. The two operators > and & must be escaped with ^ to be interpreted as literal characters on Windows command processor parsing the for command line before executing finally for which executes next %ComSpec% /c with the specified command line on which 2^>^&1 is changed already to 2>&1.
Does the log file C:\App\Debug.log contain with this modification following two lines?
'sqlcmd' is not recognized as an internal or external command,
operable program or batch file.
Yes, then no executable with file name sqlcmd is found by started cmd.exe. The best solution is referencing this executable with full qualified file name. See also: What is the reason for "X is not recognized as an internal or external command, operable program or batch file"?
Otherwise sqlcmd outputs perhaps an error message which should be now also in the log file C:\App\Debug.log.
It would be also possible to use following command line to let background cmd.exe write the error messages into a separate error log file C:\App\Error.log:
FOR /F "tokens=* USEBACKQ" %%F IN (`sqlcmd -j -S DOMAIN\SQLSERVER -U username -P password -d DBNAME -Q "UPDATE [DBNAME].[dbo].[table1] SET ColOne='V1_OFF' WHERE ColOne='V1'" 2^>C:\App\Error.log`) DO (
"tokens=* usebackq" results in first deleting all leading horizontal tabs and normal spaces on non-empty lines by for, then checking if the remaining line starts with ; in which case the line is also ignored and finally assigning the captured line not starting with ; and with leading tabs/spaces removed to loop variable F for further processing.
Better would be using the options usebackq^ delims^=^ eol^= not enclosed in double quotes which requires escaping the two spaces and the two equal signs with caret character ^ to be interpreted as literal characters by cmd.exe on parsing the command line before executing for. The line splitting behavior is disabled completed with delims= because of the definition of an empty list of delimiters. And no line except an empty line is ignored anymore because of end of line character modified from default ; to no character.
Finally a space on an echo line left to redirection operator >> is also output by echo and for that reason written as trailing space into the log file. Therefore no space should be used left to > or >> on printing a line with echo redirected into a file. But care must be taken on omitting the space character left to the redirection operator. The word left to redirection operator should not be 1, 2, ..., 9 as this would result in redirecting the output to these numbered handles into the specified file instead of the character 1, 2, etc. So if unknown text should be written into a file, it is better to specify first the redirection operator > or >> and the full qualified file name and next the echo command with the text to output. See also: Why does ECHO command print some extra trailing space into the file?
The three command lines with echo would be for this batch file:
ECHO Disabling the following...>> C:\App\Debug.log
ECHO - V1>> C:\Apps\Debug.log
>>C:\Apps\Debug.log ECHO %%F
following... is safe for being correct written into the file as also V1. %%F could be just 1 or a string ending with a space and a single digit and so it is better to specify the redirection first on the last echo command line to get finally executed by cmd.exe the command line ECHO %%F 1>>C:\Apps\Debug.log.

ssh to a server and create a directory based off a variable - all in one line

so i have a simple script that lists the folder and file structure of the current directory and spits it out to a file in the current users home directory, then rsyncs that file to a remote server into a specific folder.
the first part of the script SSH's into the remote server and creates a unique folder that the later part of the script transfers the file into.
#ssh -p 12345 sftp.domain.com ' bash -c "mkdir incoming/[foldername]" '
my question is, how can i pass a variable to this? i would usually put this in the script, and then run the script like this "copy.sh $1":
#ssh -p 12345 sftp.domain.com ' bash -c "mkdir incoming/folder-$1" '
however it doesn't work like i might hope it would. all i end up with is a folder on the remote server named "folder-" as it presumably doesn't pass the variable along with the rest when it ssh's in.
is there a better way to make this work?
the rest of the script would also reference the variable $1 to actually copy the file into the folder created on the remote server earlier in the script.
If I understand the problem correctly, the parameter you are trying to reference is set on the local client side (the command line from where you initiate the ssh connection), but you want to reference it in the command line that is to run on the remote server side. This really has nothing to do with ssh and everything to do with shell parameter/variable expansion on the local client side.
The problem is with your usage of single quotes vs. double quotes. Most Unix command shells, including bash which is likely the shell you are running on the local client side, perform environment variable expansion inside of double quotes but not inside of single quotes. So in your command line you should be able to accomplish your goal by changing the single quotes to double quotes and then escaping the embedded double quote characters like this:
#ssh -p 12345 sftp.domain.com " bash -c \"mkdir incoming/folder-$1\" "
Here is a similar example that shows this in action:
$ export EXAMPLE=abc
$ ssh localhost ' bash -c "echo $EXAMPLE def" '
def
$ ssh localhost " bash -c \"echo $EXAMPLE def\" "
abc def

Applescript: Running terminal commands and Saving output

So, I'm trying to write a script to remove wireless networks and their associated keychain credentials.
tell application "Terminal"
activate
string mywifi
set mywifi to "test"
set mywifi to do script ("networksetup -listallhardwareports | grep -A 1 'Wi-Fi' | grep -v 'Hardware' | sed -e 's/'Device:\ '//g'")
do script "networksetup -removepreferredwirelessnetwork $mywifi NETWORK1"
do script "security delete-generic-password NETWORK1"
delay 2
#do script "networksetup -removepreferredwirelessnetwork $mywifi NETWORK2"
#do script "security delete-generic-password Network2"
delay2
#do script "networksetup -removepreferredwirelessnetwork $mywifi Network3"
#do script "security delete-generic-password Network3"
delay 2
#do script "networksetup -removepreferredwirelessnetwork $mywifi Network4"
#do script "security delete-generic-password Network4"
delay 2
#do script "networksetup -removepreferredwirelessnetwork $mywifi Network5"
#do script "security delete-generic-password Network5"
delay 2
end tell
quit
Where i'm running into trouble is setting that variable with the output of that command. The command runs in terminal, though whenever I attempt to compile it, the following error is thrown
Syntax Error: Expected """ but found unknown token
It finds this right after /device:\ ' between the \ '
I have not been able to figure out what is missing. If i add " between them it just drops the terminal to >
Straight up my first foray into applescript but not my first language. I think i've been staring at it too long.
This is not intended to be a complete answer, because I'm not too familiar with the security command, although I beleive you'll need to preface it with the sudo command to modify the keychain. There's lots of good info on the Internet covering security command. I read quite a bit but there's nothing in my keychain I want to remove so I'm not able to test in this respect.
The following covers the networksetup command, which you may also need to use sudo, in Terminal, but in AppleScript add with administrator privileges at the end of the do shell script command", if necessary when preferred wireless networks.
It looks like your trying to remove all preferred wireless networks and this can be done directly in Terminal with the following command:
networksetup -removeallpreferredwirelessnetworks $(networksetup -listallhardwareports | awk '/Wi-Fi/{getline; print $2}')
If you want to do the same thing in AppleScript, e.g:
do shell script "networksetup -removeallpreferredwirelessnetworks $(networksetup -listallhardwareports | awk '/Wi-Fi/{getline; print $2}')"
If you want to use it in a bash script, then use the line above with a bash shebang, e.g.:
#!/bin/bash
networksetup -removeallpreferredwirelessnetworks $(networksetup -listallhardwareports | awk '/Wi-Fi/{getline; print $2}')
Save it in a plain text file without an extension, and make it executable, e.g. chmod u+x filename where filename is whatever you saved it as. Then to use it in Terminal, ./filename or /path/to/filename, if it's not saved in a location defined within the PATH environment variable.
If your looking to do it just for specific networks, then instead of a line for each network, you can loop through a list. If you need help with that, let us know.

Difficulty in using sed command in ssh session in shell script in solaris

I am trying to do something like this inside ssh session:
Script
ssh remoteservername "
col=`sed -n "8p" /tmp/temp.txt`
echo $col>>/tmp/Ankur.txt
"
This is not working and it is printing empty line instead of text what I want to store in col variable, why so, and this is working:
ssh remoteservername "
sed -n "8p" /tmp/temp.txt>>/tmp/Ankur.txt
"
This Ankur.txt file is on the remote server....The main focus is how to get the output of the command inside a variable so that i can use it further.
Please tell how to make it work.
Thanks
When you use double quotes the variable names will get expanded before passing them, so $col is getting expanded locally before running on the remote server. You can either escape the $ like \$col or use single quotes around it, which is probably better since you want to use double quotes inside the command as well
ssh remoteservername '
col=`sed -n "8p" /tmp/temp.txt`
echo $col>>/tmp/Ankur.txt
'
Without changing the quotes
ssh remoteservername 'sed -n "8p" /tmp/temp.txt >> /tmp/Ankur.txt'
as you noted, still works, by redirecting the output directly into the file. This avoids the variable expansion problem from the double quotes above.
If you're going to have many steps though, you might want to just create a script on remoteservername and invoke that in your ssh command rather than doing a lot on the same command line.
You can use a local file to execute complex commands and to use variables in remote machine via SSH as shown below.
1. Create a input file 'input_file.txt'
#-- input_file.txt
col=`sed -n "8p" /tmp/temp.txt`
echo $col>>/tmp/Ankur.txt
2. Execute the commands of input file in remote server via SSH
ssh remoteservername "sh -s" < input_file.txt

Unable to run a postgresql script from bash

I am learning the shell language. I have creating a shell script whose function is to login into the DB and run a .sql file. Following are the contents of the script -
#!/bin/bash
set -x
echo "Login to postgres user for autoqa_rpt_production"
$DB_PATH -U $POSTGRESS_USER $Auto_rpt_production$TARGET_DB -p $TARGET_PORT
echo "Running SQL Dump - auto_qa_db_sync"
\\i auto_qa_db_sync.sql
After running the above script, I get the following error
./autoqa_script.sh: 39: ./autoqa_script.sh: /i: not found
Following one article, I tried reversing the slash but it didn't worked.
I don't understand why this is happening. Because when I try manually running the sql file, it works properly. Can anyone help?
#!/bin/bash
set -x
echo "Login to postgres user for autoqa_rpt_production and run script"
$DB_PATH -U $POSTGRESS_USER $Auto_rpt_production$TARGET_DB -p $TARGET_PORT -f auto_qa_db_sync.sql
The lines you put in a shell script are (moreless, let's say so for now) equivalent to what you would put right to the Bash prompt (the one ending with '$' or '#' if you're a root). When you execute a script (a list of commands), one command will be run after the previous terminates.
What you wanted to do is to run the client and issue a "\i ./autoqa_script.sh" comand in it.
What you did was to run the client, and after the client terminated, issue that command in Bash.
You should read about Bash pipelines - these are the way to run programs and input text inside them. Following your original idea to solving the problem, you'd write something like:
echo '\i auto_qa_db_sync.sql' | $DB_PATH -U $POSTGRESS_USER $Auto_rpt_production$TARGET_DB -p $TARGET_PORT
Hope that helps to understand.