Pass more than one command line argument to kdb - cmd

I am trying to call a q instance with a .q script, a port and a timer from a .CMD file:
q.exe code.q -p 9001 -t 10000
It fails on -t
If I do it this way I get the timer and port set but not the .q script:
q.exe -t 10000 code.q -p 9001
Tried other switched and tried with square brackets, but I am never able to have it use those 3 arguments.
Is there a specific order?

As per the docs, the first arg after the q binary/executable must be a script, database or file (or none). A script, database or file can't be in any other position unless you're simply passing it in as a custom arg to be parsed manually (i.e. it won't auto-run/load). https://code.kx.com/q/basics/cmdline/
Your first attempt should have worked.....what was the error?

Related

A clarification on the command syntax in Kubernetes manifest files

I'm working on a question that wants me to deploy a pod with the nginx image. The pod should sleep for 5000 seconds.
The command can be specified like so:
command: ["sleep", "5000"]
or like so:
command:
- sleep
- "5000"
Why can't the command be specified like so:
command:
- sh
- -c
- sleep "5000"
or like so:
command:
- sleep "5000"
In other words, I'm confused about two things:
What does sh -c do? I understand that -c is there to denote arguments, but isn't the sleep command run using sh?
When can the command and args be listed on the same line, and when do they have to be on separate lines? In this example, why doesn't sleep "5000" work? Why do sleep and "5000" have to be on separate lines? Also, why are quotes around the number 5000 required?
Note that command and args as in K8s object definitions or manifest are in-facet entrypoint and cmd fields as found in container image definitions. These are supposed to behave in a certain specific way. for eg: if you look at at how docker images are defined, you would find entrypoint and cmd as 2 highly used fields.
supplying command and/or args in K8s object definition overrides entrypoint and cmd fields of the associated container.
entrypoint in docker image definitions for example is allowed either as a single string (sleep 5000) or as a broken down array (["sleep", "500"]). either ways, it's eventually broken down into an array of arguments (i.e. sleep 5000 becomes ["sleep", "5000"]).
I suppose K8s tries to simplify this by letting you supply this only as an array.
this article is a good reference to understand how entrypoint and cmd work in combination on container image definitions. The behavior feels a bit unnecessarily complicated and I cannot thank K8s contributors more for they simplified it to some extent at least.
The two ways of running the command:
command: ["sleep", "5000"]
Is exactly the same as:
command:
- sleep
- 5000
In both cases, it is interpreted as a list. It's two ways of expressing a list.
The command cannot be specified as command: sleep "5000" because this would be interpreted as a single argument "sleep 5000" rather than as two separate arguments sleep and 5000.
Think of it as running this command in shell:
`"sleep 5000"`
This would be run as a single command and the 5000 would not be interpreted as an argument. Whereas the expression: command: [sleep, 5000] would be interpreted as:
`"sleep"` 5000
# or simply... (same as)
`sleep` "5000"
Thus being interpreted correctly as an argument of sleep.
For sh -c, sh calls the program sh (shell) as the interpreter and the -c flag means to execute the following command as interpreted by this program. -c is the flag that tells the shell to execute the command that follows it. So in this scenario, it would be redundant to use sh -c, and I'm uncertain if that would even execute correctly.

How to run command in background and also capture the output

In the middle of the script, I have a command that exposes the local port with ssh -R 80:localhost:8080 localhost.run I need to execute this command in the background, parse the output and save it into a variable.
The output returns:
Welcome to localhost.run!
...
abc.lhrtunnel.link tunneled with tls termination, https://abc.lhrtunnel.link
Need to capture this part:
https://abc.lhrtunnel.link
As a result something like this:
...
hostname=$(command)
echo $hostname
...
Try this Shellcheck-clean code:
#! /bin/bash -p
hostname=$(ssh ... \
| sed -n 's/^.*tunneled with tls termination, //p')
declare -p hostname
I'm assuming that you don't really want to background the command that generates the output. You just want to run it in a way that allows its output to be captured and filtered. See How do you run multiple programs in parallel from a bash script? for information about how "background" processes are used for parallel processing.
The -n option to sed means that it doesn't print lines from the input unless explicitly instructed to print.
s/^.*tunneled with tls termination, //p works on input lines that contain anything followed by the string tunneled with tls termination, . It deletes everything on the line up to the end of that string and prints the result, which hopefully will be the URL that you want.
declare -p varname is a much more reliable and useful way to show the value of a variable than using echo.

String variable output showing strange Single Quote in Bash

I have following scripts
#!/bin/bash
set -o xtrace
gluster_volume="a.example.com:/data/brick1/gv0 b.example.com:/data/brick1/gv0"
gluster volume create gv0 replica 2 ${gluster_volume} force
While executing second line this script throwing error related to gluster_volume that its unable read complete line and just considering a.example.com:/data/brick1/gv0 b.example.com(so look like gluster command not able parse it).
Then I run this script with trace and found that command is like
gluster volume create gv0 replica 2 'a.example.com:/data/brick1/gv0 b.example.com:/data/brick1/gv0' force
so script is adding single quotes which are creating problem. I was under the impression that it's due to set -o xtrace the single quotes are not part of the value, just part of the displayed command line. But its not true. if i run above command on command prompt it gives same error and on removing quotes it works.
How i can change my script so it don't add quotes? (I tried to remove quote with sed but not working, something happening at run time).
I need gluster_volume with dynamic values.
Update1:
workers=`echo "${WORKER_HOST_IP}"|sed "s/,$//"`
IFS=','
for worker in ${workers}; do
IFS='-' read -r -a array <<< "$worker"
gluster_volume+=${array[0]}':/data/brick1/gv0 '
done
You can try eval(Be careful if the list of bricks or the string comes from an external untrusted source)
#!/bin/bash
set -o xtrace
gluster_volume="a.example.com:/data/brick1/gv0 b.example.com:/data/brick1/gv0"
eval "gluster volume create gv0 replica 2 ${gluster_volume} force"

Bash commands as variables failing when joining to form a single command

ssh="ssh user#host"
dumpstructure="mysqldump --compress --default-character-set=utf8 --no-data --quick -u user -p database"
mysql=$ssh "$dumpstructure"
$mysql | gzip -c9 | cat > db_structure.sql.gz
This is failing on the third line with:
mysqldump --compress --default-character-set=utf8 --no-data --quick -u user -p database: command not found
I've simplified my actualy script for the purpose of debugging this specific error. $ssh and $dumpstructure aren't always being joined together in the real script.
Variables are meant to hold data, not commands. Use a function.
mysql () {
ssh user#host mysqldump --compress --default-character-set=utf8 --nodata --quick -u user -p database
}
mysql | gzip -c9 > db_structure.sql.gz
Arguments to a command can be stored in an array.
# Although mysqldump is the name of a command, it is used here as an
# argument to ssh, indicating the command to run on a remote host
args=(mysqldump --compress --default-character-set=utf8 --nodata --quick -u user -p database)
ssh user#host "${args[#]}" | gzip -c9 > db_structure.sql.gz
Chepner's answer is correct about the best way to do things like this, but the reason you're getting that error is actually even more basic. The line:
mysql=$ssh "$dumpstructure"
doesn't do anything like what you want. Because of the space between $ssh and "$dumpstructure", it'll parse this as environmentvar=value command, which means it should execute the "mysqldump..." part with the environment variable mysql set to ssh user#host. But it's worse than that, since the double-quotes around "$dumpstructure" mean that it won't be split into words, and so the entire string gets treated as the command name (rather than mysqldump being the command name, and the rest being arguments to it).
If this had been the right way to go about building the command, the right way to stick the parts together would be:
mysql="$ssh $dumpstructure"
...so that the whole combined string gets treated as part of the value to assign to mysql. But as I said, you really should use Chepner's approach instead.
Actually, commands in variables should also work and can be in form of `$var` or just $($var). If it says command not found, it could because the command maybe not in you PATH. Or you should give full path of you command.
So let's put this vote down away and talk about this question.
The real problem is mysql=$ssh "$dumpstructure". This means you'll execute $dumpstructure with additional environment mysql=$ssh. So we got command not found exception. It's actually because mysqldump is located on remote server not this host, so it's reasonable this command is not found.
From this point, let's see how to fix this question.
OP want to dumpplicate mysql data from remote server, which means $dumpstructure shoud be executed remotely. Let's see third line mysql=$ssh "$dumpstructure". Now we figure out this would result in problem. So what should be the correct command? The simplest command should be like mysql="$ssh $dumpstructure", which means both $ssh and $dumpstructure will be join into single command line in variable $mysql.
At the end, let's talk about the last command line. I do not agree with variable are meant to hold data, not command. Cause command is also a kind of data. The real problem is how to use it correctly.
OP's command is also supported, at least it is supported on bash 4.2.46.
So the real problem is how to use a variable to hold commands not import a new method to do that, wraping them into a bash function, for example.
So who can tell me why this answer does not come into readers' notice but be voted down?

Want to read variable value from remote file

In one of my bash script I want to read and use the variable value from other script which is on remote machine.
How should I go ahead to resolve this. Any related info would be helpful.
Thanks in advance!
How about this (which is code I cannot currently test myself):
text=$(ssh yourname#yourmachine 'grep uploadRate= /root/yourscript')
It assumes that the value of the variable is contained in one line. The variable text now contains you variable assignment, presumably something like
uploadRate=1MB/s
There are several ways to convert the text/code into a real variable assignment in your current script, like evaluating the string or using grep. I would recommend
uploadRate=${text#*=}
to just remove the part up and including the =.
Edit: One more caveat to mention is that this only works if the original assignment does not contain variable references itself like in
uploadRate=1000*${kB}/s
ssh user#machine 'command'
will print the standard output of the remote command.
I would tell two ways at least:
1) You can simply redirect output to a file from remote server to your system with scp command...It would work for you.Then your script on your machine should read that file as an argument...
script on your machine:
read -t 50 -p "Waiting for argumet: " $1
It waits for output from remote machine,
Then you can
sshpass -p<password> scp user#host:/Path/to/file /path/to/script/
What you need to do:
You should tell the script from your machine, that the output from scp command is the argument($1)
2)Run script from your machine:
#!/bin/bash
script='
#Your commands
'
sshpass -p<password> ssh user#host $script
And you have also another ways to run script to do sth with remote machine.

Resources