I am trying to open and externally managed shell and trying to run some command in makefile. How can I do that?
For example, if I want to run the following sequence in my make file:
> python
> a = 6
> b = 5
> c = a + b
> print(c)
>exit()
This is a sample of externally managed shell that I am trying.
There are various ways, none of them super-simple. Here's the most basic one:
runcommand:
( echo 'a = 6'; \
echo 'b = 5'; \
echo 'c = a + b'; \
echo 'print(c)'; \
echo 'exit()'; \
) | python
Basically, if you can write the command in a single shell command line, then you can transpose that command line into your makefile recipe.
Related
I am learning Makefile and trying to implement parallelism. I am aware of the "-j" option. However, for example having the following makefile (on Windows)-
all: a b c d
a:
# some build rule
b:
# some build rule with parallelism
c:
# some build rule
d:
#some build rule
I am trying to run make all with only target "b" running in parallel. Passing the -j option with the build rule for "b" doesn't work. Any pointers?
You could get b's recipe to run in the background as so:
all: a b c d
#echo running $#
.PHONY: a b c d all
a c d: | b
#echo -n _$#0 && \
sleep 1 && echo -n _$#1 && \
sleep 1 && echo _$#2
b:
#(echo -n _$#0 && \
sleep 2 && echo -n _$#1 && \
sleep 2 && echo -n _$#2\
) &
Which outputs:
_b0_a0_a1_b1_a2
_c0_c1_b2_c2
_d0_d1_d2
running all
The order-only dependency on b makes b run first, otherwise it wouldn't start until after a completes with -j1... It does of course mean that you have to build b if you build either a c or d.
Alternatively, (and I'm not recommending this) you could use some manual locking mechanism such as flock to prevent a, c, and d from running in parallel (note that the flock only protects a single shell, so you would have to collapse your recipes into a single line protected by flock for this to work).
Sorry, I'm from Brazil and my english is not fluent.
I wanna concatenate 20 files using a shellscript through cat command. However when I run it from a file, all content of files are showed on the screen.
When I run it directly from terminal, works perfectly.
That's my code above:
#!/usr/bin/ksh
set -x -a
. /PROD/INCLUDE/include.prod
DATE=`date +'%Y%m%d%H%M%S'`
FINAL_NAME=$1
# check if all paremeters are passed
if [ -z $FINAL_NAME ]; then
echo "Please pass the final name as parameter"
exit 1
fi
# concatenate files
cat $DIRFILE/AI6LM760_AI6_CF2_SLOTP01* $DIRFILE/AI6LM761_AI6_CF2_SLOTP02* $DIRFILE/AI6LM763_AI6_CF2_SLOTP04* \
$DIRFILE/AI6LM764_AI6_CF2_SLOTP05* $DIRFILE/AI6LM765_AI6_CF2_SLOTP06* $DIRFILE/AI6LM766_AI6_CF2_SLOTP07* \
$DIRFILE/AI6LM767_AI6_CF2_SLOTP08* $DIRFILE/AI6LM768_AI6_CF2_SLOTP09* $DIRFILE/AI6LM769_AI6_CF2_SLOTP10* \
$DIRFILE/AI6LM770_AI6_CF2_SLOTP11* $DIRFILE/AI6LM771_AI6_CF2_SLOTP12* $DIRFILE/AI6LM772_AI6_CF2_SLOTP13* \
$DIRFILE/AI6LM773_AI6_CF2_SLOTP14* $DIRFILE/AI6LM774_AI6_CF2_SLOTP15* $DIRFILE/AI6LM775_AI6_CF2_SLOTP16* \
$DIRFILE/AI6LM776_AI6_CF2_SLOTP17* $DIRFILE/AI6LM777_AI6_CF2_SLOTP18* $DIRFILE/AI6LM778_AI6_CF2_SLOTP19* \
$DIRFILE/AI6LM779_AI6_CF2_SLOTP20* > CF2_FINAL_TEMP
mv $DIRFILE/CF2_FINAL_TEMP $DIRFILE/$FINAL_NAME
I solved the problem putting the cat block inside a function, and redirecting stdout to the final file.
Ex:
concatenate()
I define a function in Makefile
define write_file
for i in $( seq 1 10 )
do
echo "1234567" >> "tmp/test.txt"
done
endef
And
pre:
mkdir -p exe tmp
${call write_file}
But when I make pre,I got error:
mkdir -p exe tmp
for i in
/bin/sh: 1: Syntax error: end of file unexpected
Each line of a make-recipe is a single command that make runs in a single
new shell. So you need to make the body of the macro write_file into a single
shell command.
In addition, make expands anything of the unescaped form $(....),
treating .... as a defined or undefined make expression. So in your
case, make expands $( seq 1 10 ) to nothing. To stop make doing
that and let the shell expand $( seq 1 10 ), you need to escape $ for make,
which you do by writing $$ instead. The same goes for any $ in a make-recipe
that you intend to be expanded by the shell.
Putting these points together, you want:
define write_file
for i in $$( seq 1 10 ); \
do \
echo "1234567" >> "tmp/test.txt"; \
done
endef
I'm creating a script like this
#!/bin/csh
set h=1;
while [h=1] do echo "hi"; h=2; done;
but when I execute it a get this:
===> message after : csh test.sh [h=1]: No match.
Try:
set h = 1
while ( $h == 1 )
echo "hi"
set h = 2
end
You seem to be trying to mix Bourne shell syntax into your C shell script.
Csh is generally a lousy language for scripting, try to avoid it if at all possible
http://www.faqs.org/faqs/unix-faq/shell/csh-whynot/
UPDATE:
The csh equivalent to read h is:
set h = $<
This program I use has it's own variables to set when you run it, so I want to set those variables and then greping the output then storing it inside a variable. However, I don't know how to go about this the correct way. The idea I have doesn't work. The focus is on lines 7 through 14.
1 #!/usr/local/bin/bash
2 source /home/gempak/NAWIPS/Gemenviron.profile
3 FILENAME="$(date -u '+%Y%m%d')_sao.gem"
4 SFFILE="$GEMDATA/surface/$FILENAME"
5 echo -n "Enter the station ID: "
6 read -e STATION
7 OUTPUT=$(sflist << EOF
8 SFFILE = $SFFILE
9 AREA = #$STATION
10 DATTIM = all
11 SFPARM = TMPF;DWPF
12 run
13 exit
14 EOF)
15 echo $OUTPUT
But I get this:
./listweather: line 7: unexpected EOF while looking for matching `)'
./listweather: line 16: syntax error: unexpected end of file
Putting together everyone's answers, I came across a working solution myself. This code works for me:
#!/usr/local/bin/bash
source /home/gempak/NAWIPS/Gemenviron.profile
FILENAME="$(date -u '+%Y%m%d')_sao.gem"
SFFILE="$GEMDATA/surface/$FILENAME"
echo -n "Enter the station ID: "
read -e STATION
OUTPUT=$(sflist << EOF
SFFILE = $SFFILE
AREA = #$STATION
DATTIM = ALL
SFPARM = TMPF;DWPF
run
exit
EOF
)
echo $OUTPUT | grep $STATION
Thanks everyone!
I'd put your program to run in a separate .sh script file, and then run the script from your first file, passing the arguments you want to pass as command line arguments. That way you can test them separately.
You could also do it in a function, but I like the modularity of the second script. I don't udnerstand exactly what you are trying to do above, but something like:
runsflist.sh:
#!/bin/bash
FILENAME="$(date -u '+%Y%m%d')_sao.gem"
SFFILE="$GEMDATA/surface/$FILENAME"
AREA = #$STATION
DATTIM = all
SFPARM = TMPF;DWPF
grep $STATION | sflist
main.sh:
#!/bin/bash
echo -n "Enter the station ID: "
read -e STATION
OUTPUT=`runsflist.sh`
echo $OUTPUT
If sflist needs interaction, I'd try something like this:
SFFILE=$(
( echo SFFILE = "$SFFILE"
echo AREA = "#$STATION"
echo DATTIM = all
echo SFPARM = TMPF;DWPF
echo run
cat
) | sflist)
Unfortunately, you have to type exit as part of the interaction.