How to send array values by mail - arrays

in linux scripting,
is there a way to use mail function to one time send array values??
function my_mail_function(){
# send array values
mail array_values_here "mymail#domain.tld" ;
}
Thank you

You can step through an array with just a little bit of bash code.
#!/bin/bash
# Here's a simple array...
a=(one two three)
# The brackets encapsulate multiple commands to feed to the stdin of sendmail
(
echo "To: Mister Target <target#example.com>"
echo "From: Julio Fong <jf#example.net>"
echo "Subject: Important message!"
echo ""
count=1
for item in ${a[#]}; do
printf "Value %d is %s\n" "$count" "$item"
((count++))
done
echo ""
) | /usr/sbin/sendmail -oi -fjf#example.net target#example.com
Note that it'll be safer to use sendmail directly rather than relying on the availability and configuration of a mail or Mail command. Your sendmail binary may not be in the same place as mine; if /usr/sbin/ doesn't work for you, check /usr/libexec/. It'll depend on the distribution of Linux you're running.

The proper way to use mail is:
mail -s "subject here" recipient1 recipient2 ...
the command reads the email body from stdin so you can format it how you like and read it in from a pipe or a here-doc or a file or ...
function my_mail_function(){
printf "%s\n" "${array_var[#]}" | mail -s "array values" mymail#domain.tld
}

Related

Passing variables (array index) from remote ssh to global function

BASH
I'm writing a script to check services on a selection of hosts for a selection of users. The selected users are stored in an array. The script connects via ssh to each selected host and would go looping through the array logging in to each selected user. However the script fails to read the index of array given by for cycle during ssh - it takes only the 1st (0) index of the array. I've tried almost every possible quoting, escaping, etc... When i escape the $j variable in the echo or "checking" step, i get a syntax error: operand expected (error token is ā€œ$jā€) error. Any ideas on how to make it work? Is it even possible?
usr1=("user1" "user2")
function tusr {
declare -n tmpp="$1";
echo "${tmpp[$j]}"
}
function testchk {
echo "Logging in as $myuser to $1"
ssh -tq $myuser#$1.bar.com "
for j in ${!usr1[#]}; do
echo \$j
echo ${usr1[$j]}
echo "Checking $(tusr usr1 "\$j"):"
done
"
}
srv="foo"
testchk "$srv"
When echoing the escaped $j, it prints out the correct value.
My output:
0
user1
Checking user1:
1
user1
Checking user1:
Expected output:
0
user1
Checking user1:
1
user2
Checking user2:
The remote shell doesn't know of your local variables or functions, so you'll need to pass their declarations.
ssh -tq $myuser#$1.bar.com "
$(declare -p usr1)
$(declare -f tusr)
for j in \${!usr1[#]}
do
echo \"\$j\"
echo \"\${usr1[\$j]}\"
echo \"Checking \$(tusr usr1 \$j):\"
done
"
But what you're trying to do is a real mix of things and it's confusing. Are you trying to make the remote user to execute the function tusr locally ??

SGE array jobs and R

I currently have a R script written to perform a population genetic simulation, then write a table with my results to a text file. I would like to somehow run multiple instances of this script in parallel using an array job (my University's cluster uses SGE), and when its all done I will have generated results files corresponding to each job (Results_1.txt, Results_2.txt, etc.).
Spent the better part of the afternoon reading and trying to figure out how to do this, but haven't really found anything along the lines of what I am trying to do. I was wondering if someone could provide and example or perhaps point me in the direction of something I could read to help with this.
To boil down mithrado's answer to the bare essentials:
Create job script, pop_gen.bash, that may or may not take SGE task id argument as input, storing results in specific file identified by same SGE task id:
#!/bin/bash
Rscript pop_gen.R ${SGE_TASK_ID} > Results_${SGE_TASK_ID}.txt
Submit this script as a job array, e.g. 1000 jobs:
qsub -t 1-1000 pop_gen.bash
Grid Engine will execute pop_gen.bash 1000 times, each time setting SGE_TASK_ID to value ranging from 1-1000.
Additionally, as mentioned above, via passing SGE_TASK_ID as command line variable to pop_gen.R you can use SGE_TASK_ID to write to output file:
args <- commandArgs(trailingOnly = TRUE)
out.file <- paste("Results_", args[1], ".txt", sep="")
# d <- "some data frame"
write.table(d, file=out.file)
HTH
I am not used to do this in R, but I've been using the same approach in python. Imagine that you have an script genetic_simulation.r and it has 3 parameter:
--gene_id --khmer_len and --output_file.
You will have one csv file, genetic_sim_parms.csv with n rows:
first_gene,10,/result/first_gene.txt
...
nth_gene,6,/result/nth_gene.txt
A import detail is the first lane of your genetic_simulation.r. It needs to tell which executable the cluster is going to will use. You might need to tweak its parameters as well, depending on your setup, it will look like to:
#!/path/to/Rscript --vanilla
And finally, you will need a array-job bash script:
#!/bin/bash
#$ -t 1:N < change to number of rows in genetic_sim_parms.csv
#$ -N genetic_simulation.r
echo "Starting on : $(date)"
echo "Running on node : $(hostname)"
echo "Current directory : $(pwd)"
echo "Current job ID : $JOB_ID"
echo "Current job name : $JOB_NAME"
echo "Task index number : $SGE_TASK_ID"
ID=$(awk -F, -v "line=$SGE_TASK_ID" 'NR==line {print $1}' genetic_sim_parms.csv)
LEN=$(awk -F, -v "line=$SGE_TASK_ID" 'NR==line {print $2}' genetic_sim_parms.csv)
OUTPUT=$(awk -F, -v "line=$SGE_TASK_ID" 'NR==line {print $3}' genetic_sim_parms.csv)
echo "id is: $ID"
rscript genetic_simulation.r --gene_id $ID --khmer_len $LEN --output_file $OUTPUT
echo "Finished on : $(date)"
Hope this helps!

Alternative to Cat out of a bash script?

i have an issue with the following.
exec 3<>/dev/tcp/$1/37491
echo -ne 060e2b3 00$hexdec$cmdhex | perl -pe 's/([0-9a-f]{2})/chr hex $1/gie' >&3
cat <&3
i have a server in which i send a hex string to with the port / tcp connection made. BUT since i am using putty through a terminal my first issue is that the XML response back always says PuTTY and it doesnt escape. I also need to put the replies back sometimes in an array and i have tried
array=`cat <&3`
echo "Array items:"
for item in ${array[*]}
do
printf " %s\n" $item
done
and i believe since the cat is not exiting properly it just stays open the array is not done?
thanks for the advanced help
Do you need specify a timeout?
while read -t 5 line <&3; do
echo "$line"
(( Lines++ ))
done
exec 3>&-
Perhaps you need to close the TCP/IP socket?
exec 3>&-

Handle ctrl +d programmatically?

I am trying to execute the following perl script.
##some code
$command = "nail -s this is a test $email";
system($command);
##some code
when I run this script, it hangs until I press CtrlD. after pressing CtrlD I get the desired result. My question is how can I hardcode CtrlD in my script?
I suppose you call mailx. nail ist most likely an alias. It expects input from STDIN, which is ended with CtrlD. You could workaround like this to send an empty mail:
$command = 'echo "" | nail -s SUBJECT ' . $email;
The mail program expects an . on a line alone to show it is the end of the message
Just make sure your $email contains a \n. and it should no longer hang.
The usual solution is to redirect it to read from /dev/null
Try to use this :
mail -s "Hello Test" -a Attachment email-address </dev/null
or, if you have any email body
mail -s "Hello Test" -a Attachment email-address <emailbodyfile.txt

Basic bash script arguments

I'm new to bash script and wanted to know how to do the following. Basically I have the following line
./application [channels] -> [message]
where I would like to store these into 2 bash variables with the '->' as the delimiter.
ie:
$channels = channels
$message = message
Furthermore, there can be multiple channels separated by a , and/or a space. So the full line would be something like this:
./application Channel1, Channel2,Channel3 -> This is a message.
Now in bash, I would like the channels stored in a channels array separated by , (and get rid of the space if its there) and message stored in a message variable. The only thing I can put together at the moment is this:
#!/bin/bash
for i
do
echo $i
done
can someone help me out?
Since you're likely to have spaces in your message, keep your arguments in quotes, and you keep it simple:
for CHANNEL in $(echo $1 | tr " ," "\n")
do
echo Channel: ${CHANNEL}
done
echo Message: ${2}
Example:
anew#buddha:~/dev/so$ bash example.sh "channel1 channel2 channel3" "this is the message"
Channel: channel1
Channel: channel2
Channel: channel3
Message: this is the message

Resources