I'm trying to do a script that does things on my linux computer but does not respects wait commands.
That's my code that does not work
cat file.txt | while read line || [[ -n $line ]]; do
do
QUEST="$(./fi $line | grep -oE " fi " &> A.txt; echo $? >"$dir")" & proc=$!
wait "$proc"
read ret <"$dir"
if [[ "$QUEST" != "" ]];then echo "$line" &>> A.txt; fi; unset QUEST;
done &> /dev/null & wait
It have to do one quest a time and save the output (that could exists or not).
When you run a command in the background, it's run in a subshell. Any variable assignments are not visible in the original shell, so the assignment to QUEST doesn't work.
You don't need to do that in the background, since you're immediately waiting for the command to finish. Just run it normally.
while read line || [[ -n $line ]]; do
do
QUEST="$(./fi $line | grep -oE " fi " &> A.txt)"
ret=$?
if [[ "$QUEST" != "" ]]
then echo "$line" &>> A.txt
fi
done &> /dev/null < file.txt
unset QUEST
There's also no need to write $? to $dir. The exit status of a variable assignment from a command substitution is the exit status of the command.
I'm building a script for php-fpm compilation, installation and deployment in ubuntu 14. At one point, I have got to generate another file using this main script. The resulting file is a script and should have all variables BUT one NOT expanded.
So I started with cat << 'EOT' in will of resolving the thing after the file generation with sed. But I find myself in a "logic" blackhole.
As for the EOT quoting beeing an issue for expanding just one variable, the same is for the sed line. I went straight writing the following, then laught at it without even executing it, of course.
sed -i 's/\$PhpBuildVer\/$PhpBuildVer' /etc/init.d/php-$PhpBuildVer-fpm
OR
sed -i "s/\$PhpBuildVer\/$PhpBuildVer" /etc/init.d/php-$PhpBuildVer-fpm
both would fail, while I need the first pattern to be the "$PhpBuildVer" itself and the other one beeing the expanded variable, for instance, 7.1.10.
How would I perform this substituion with either sed or another GNU Linux command?
This is my script, most of the parts have been cut-off as non question related.
#!/bin/bash
PhpBuildVer="7.1.10"
... #removed non relevant parts of the script
cat << 'EOT' >> /etc/init.d/php-$PhpBuildVer-fpm
#! /bin/sh
### BEGIN INIT INFO
# Provides: php-$PhpBuildVer-fpm
# Required-Start: $all
# Required-Stop: $all
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: starts php-$PhpBuildVer-fpm
# Description: starts the PHP FastCGI Process Manager daemon
### END INIT INFO
php_fpm_BIN=/opt/php-$PhpBuildVer/sbin/php-fpm
php_fpm_CONF=/opt/php-$PhpBuildVer/etc/php-fpm.conf
php_fpm_PID=/opt/php-$PhpBuildVer/var/run/php-fpm.pid
php_opts="--fpm-config $php_fpm_CONF"
wait_for_pid () {
try=0
while test $try -lt 35 ; do
case "$1" in
'created')
if [ -f "$2" ] ; then
try=''
break
fi
;;
'removed')
if [ ! -f "$2" ] ; then
try=''
break
fi
;;
esac
echo -n .
try=`expr $try + 1`
sleep 1
done
}
case "$1" in
start)
echo -n "Starting php-fpm "
$php_fpm_BIN $php_opts
if [ "$?" != 0 ] ; then
echo " failed"
exit 1
fi
wait_for_pid created $php_fpm_PID
if [ -n "$try" ] ; then
echo " failed"
exit 1
else
echo " done"
fi
;;
stop)
echo -n "Gracefully shutting down php-fpm "
if [ ! -r $php_fpm_PID ] ; then
echo "warning, no pid file found - php-fpm is not running ?"
exit 1
fi
kill -QUIT `cat $php_fpm_PID`
wait_for_pid removed $php_fpm_PID
if [ -n "$try" ] ; then
echo " failed. Use force-exit"
exit 1
else
echo " done"
echo " done"
fi
;;
force-quit)
echo -n "Terminating php-fpm "
if [ ! -r $php_fpm_PID ] ; then
echo "warning, no pid file found - php-fpm is not running ?"
exit 1
fi
kill -TERM `cat $php_fpm_PID`
wait_for_pid removed $php_fpm_PID
if [ -n "$try" ] ; then
echo " failed"
exit 1
else
echo " done"
fi
;;
restart)
$0 stop
$0 start
;;
reload)
echo -n "Reload service php-fpm "
if [ ! -r $php_fpm_PID ] ; then
echo "warning, no pid file found - php-fpm is not running ?"
exit 1
fi
kill -USR2 `cat $php_fpm_PID`
echo " done"
;;
*)
echo "Usage: $0 {start|stop|force-quit|restart|reload}"
exit 1
;;
esac
EOF
#Here the variable should be substituted.
chmod 755 /etc/init.d/php-$PhpBuildVer-fpm
... #removed non relevant parts of the script
I am not 100% sure, but I think what you are looking for is:
sed -i 's/\$PhpBuildVer/'"$PhpBuildVer"'/' /etc/init.d/php-$PhpBuildVer-fpm
You can actually put two quoted expressions right next to each other in bash. E.g., echo '12'"34"'56' will output 123456. In this case, the first \$PhpBuildVer is in '' so it can match literally, and the second is in "" so that it will be expanded.
(But maybe you should consider using a template file and php, or (blatant plug)
perlpp* to build the script, rather than inlining all the text into your main script. ;) )
Edit by the way, using cat ... >> rather than cat ... > means you will be appending to the script unless you have rmed it somewhere in the code you didn't show.
Edit 2 If $PhpBuildVer has any characters in it that sed interprets in the replacement text, you might need to escape it:
repl_text="$(sed -e 's/[\/&]/\\&/g' <<<"$PhpBuildVer")"
sed -i 's/\$PhpBuildVer/'"$repl_text"'/' /etc/init.d/php-$PhpBuildVer-fpm
Thanks to this answer by Pianosaurus.
Tested example
I put this in make.sh:
#!/bin/bash
f=42 # The variable we are going to substitute
cat <<'EOT' >"test-$f.sh" # The script we are generating
#!/bin/sh
# Provides: test-$f.sh
echo 'Hello, world!'
EOT
echo "test-$f.sh before substitution is:"
echo "---------"
cat "test-$f.sh"
echo "---------"
sed -i 's/\$f/'"$f"'/' "test-$f.sh" # The substitution, from above
echo "test-$f.sh after substitution is:"
echo "---------"
cat "test-$f.sh"
echo "---------"
The output I get is:
test-42.sh before substitution is:
---------
#!/bin/sh
# Provides: test-$f.sh
echo 'Hello, world!'
---------
(note the literal $f)
test-42.sh after substitution is:
---------
#!/bin/sh
# Provides: test-42.sh
echo 'Hello, world!'
---------
(now the $f is gone, and has been replaced with its value, 42)
perlpp example
Since *I am presently the maintainer of perlpp, I'll give you that example, too :) . In a template file that I called test.template, I put:
#!/bin/sh
# Provides: test-<?= $S{ver} ?>.sh
echo 'Hello, world!'
That was exactly the content of the script I wanted, but with <?= $S{ver} ?> where I wanted to do the substitution. I then ran
perlpp -s ver=\'7.1.10\' test.template
(with escaped quotes to pass them to perl) and got the output:
#!/bin/sh
# Provides: test-7.1.10.sh
echo 'Hello, world!'
:)
Any -s name=\'value\' command-line argument to perlpp creates $S{name}, which you can refer to in the template.
<?= expr ?> prints the value of expression expr
Therefore, <?= $S{name} ?> outputs the value given on the command line for name.
Just break up the heredoc. eg
cat > file << 'EOF'
This line will not be interpolated: $FOO
EOF
cat >> file << EOF
and this line will: $FOO
EOF
If for some reason you do want to used sed as well, don't do it after, just use it instead of cat:
sed 's#foo#bar#g' >> file << EOF
this line's foo is changed by sed, with interpolated $variables
EOF
I have a process I start on my shell that prints out data and I have a python script that calculates it and should return that to the process. How can I do that?
I know using pipe or > could help me with one side, but how can I achieve a two-way redirection?
Is something like: my_process | my_script | my_process legal?
What I want to happen:
start process from shell
process sends data to my script (instead of printing it to STDOUT)
my script returns an answer to process (instead of printing it to
STDOUT)
return to step 2
It's emulatable with FIFOs (or if you're using python, you can create your own pipes with the pipe system call and redirect them according to your arrangement).
Some example code:
#!/bin/sh
#note: the resource management and error handling here is not very clean or robust
mkfifo fifo0 fifo1
exec 3<>fifo0
exec 4<>fifo1
rm -f fifo0 fifo1
many()
{
i=0
while [ $i -lt $1 ]; do
echo -n x
i=$((i+1))
done
echo
}
proc1()
{
ulimit_p=$(ulimit -p)
while :; do
echo proc1_msg
echo >&2 proc1_written=proc1_msg
read var
echo >&2 proc1_read=$var
sleep 1
done
}
proc2()
{
while :; do
read var
echo >&2 proc2_read=$var
echo proc2_msg
echo >&2 proc2_written=proc2_msg
done
}
pid=0
trap 'echo kill $pid; kill $pid; exit 130' INT
proc1 <&3 >&4 & pid=$!
proc2 <&4 >&3
I've got my script going as far as It can connect, login and run the command. But I'm stuck as how do I save the response from the command to a file, without saving the whole session.
#!/bin/sh
Var=1
while [ $Var -lt 20 ]
do
HOST='IPa.ddr.ess.'$Var
USER='MyUser'
PASSWD='MyPassword'
CMD='MyCommand'
(
echo open "$HOST"
sleep 1
echo "$USER"
sleep 1
echo "$PASSWD"
sleep 1
echo "$CMD"
#I want to save the output from my $cmd to an varaible $Output
#Then I want to write "$HOST - $Output" to a file named "output.txt"
sleep 2
echo "exit"
) | telnet
Var=$((Var + 1))
done
I'd appreciate any help, or pointers in the right direction
Ok, this looks more challenging than I initially thought. I like it :-)
#!/bin/sh
Var=1
while [ $Var -lt 20 ]
do
HOST='IPa.ddr.ess.'$Var
USER='MyUser'
PASSWD='MyPassword'
CMD='MyCommand'
MARKER='XXXX1234:AUIE'
(echo "$HOST - " ; (
echo unset echo
echo open "$HOST"
sleep 1
echo "$USER"
sleep 1
echo "$PASSWD"
sleep 1
echo echo "$MARKER"
echo "$CMD"
#I want to save the output from my $cmd to an varaible $Output
#Then I want to write "$HOST - $Output" to a file named "output.txt"
sleep 2
echo "exit"
) | telnet | sed -e "1,/$MARKER/d" ) >> output.txt
Var=$((Var + 1))
done
What this does is:
it disables echo-ing in telnet
After the login session, it prints a marker
anything after the marker is saved into output.txt
I imbricated into yet another shell that will print the "$HOST -" part
My for loop is not running within shell when the function end_process is executed. Similar for loops run outside of a function declaration. I'm wondering why it doesn't run or how to make it run.
function end_process {
{
echo "stopped on $(date)"
echo "$arguments_line"
echo "$invalid_arguments_line"
} >> spy.log
for ((i=0; i<counter; i++)); do
echo "${usernames[$i]}" >> spy.log
echo "test line"
done
echo "007 Signing Out"
exit 0
}
I'm using bash
#!/bin/bash
Also tried this
function end_process {
{
echo "stopped on $(date)"
echo "$arguments_line"
echo "$invalid_arguments_line"
} >> spy.log
for i in `seq 0 $counter`
do
#for ((i=0; i<counter; i++)); do
echo "i is $i"
echo "${usernames[$i]}" >> spy.log
echo "test line"
done
echo "007 Signing Out"
exit 0
}
but neither worked
Problem was that I was calling the function
trap end_process SIGUSR1
but we need to put in escape strings for the function name
trap 'end_process' SIGUSR1
I guess this was just a common problem with RTFM