I currently have a Makefile rule thus:
start:
./start.sh
which starts a very simple server needed as part of the build process. I have another rule for stopping the server:
stop:
kill `cat bin/server.PID`
here is the start.sh script:
#!/bin/bash
cd bin
python server.py &
echo $! > server.PID
NB server.py must be run from within the bin directory
I'd like to implement the functionality of start.sh within the start rule, I've tried numerous things but can't seem to get the PID.
I don't understand where you're getting stuck.
What's wrong with
start:
cd bin && { python server.py & echo $$! > server.PID; }
?
You can also make the pidfile a target and dependency:
start: server.PID
server.PID:
cd bin && { python server.py & echo $$! > $#; }
stop: server.PID
kill `cat $<` && rm $<
.PHONY: start stop
Related
I have recently installed Git For Windows version 2.19.1.windows.1 in my Windows 64Bit (both Windows 7 and 10, in two systems).
Now I have created below script to do some regular tasks easily w/o writing every instruction separately:
#!/bin/bash
## Contains functions and methods that can be executed inside Vagrant SSH Session
export SCRIPT_PATH="$(cd "$(dirname "$0")"; pwd -P)"
export PROJECT_ROOT_PATH="/var/www" PROJECT_ROOT_DIR="/var/www" ROOT_FOLDER="/var/www"
function fcc() {
echo "########## Frontend Cache clear begins #############"
[[ "$PWD" =~ "frontend/app" ]] && cd frontend/app
rm -rf webroot/cache_js && rm -rf webroot/cache_css
mkdir -m 777 webroot/cache_js && mkdir -m 777 webroot/cache_css
Console/cake AssetCompress.AssetCompress build -f
cat /dev/null > ~/.bash_history && history -wc && history -cw && exit
cd /var/www
echo "########## Frontend Cache clear ends #############"
keep_shell_open
}
function bocc() {
...
}
function bcc() {
...
}
function succ() {
...
}
function keep_shell_open() { exec $SHELL; };
Now when goto script's directory thro' Gitbash terminal & I register the script as below it unexpectedly opens the C:\Program Files\Git\usr\bin directory of GitBash:
. ./VagrantGuestScript.sh
And then when I execute the "fcc" function of this script, it only executes first 2 or 3 lines and then closes the terminal.
Can anyone explain why it opens Gitbash's bin path when trying to register the script & why it closes the terminal after executing only 2/3 lines of the function "fcc" ?
I use a Makefile to compile latex. In the end of the compile process I have the following rule
$(PDFREADER) $(SOURCE).pdf &
where it will open in evince the newly created pdf.
What I want is that next time I compile the pdf, the Makefile closes the current evince process, opened in during previous the compilation.
I read this and this posts, but I did not understand how to do it.
Any help?
Thanks
EDIT this is the makefile I use
SOURCE=PEI
PDFREADER=evince
EXTENSIONS=ps dvi log out toc aux bbl blg idx glg glo ist lof acn ilg ind ist lot xdy synctex.gz glsdefs
$(SOURCE).pdf: $(SOURCE).tex bibliografia.bib
if [ -a evince.PID ]; then \
kill -TERM $$(cat evince.PID) || true; \
fi;
pdflatex -shell-escape $(SOURCE).tex
bibtex $(SOURCE)
pdflatex -shell-escape $(SOURCE).tex
pdflatex -shell-escape $(SOURCE).tex
vis: $(SOURCE).pdf
$(PDFREADER) $(SOURCE).pdf & echo $$! > evince.PID
clean: organized
#rm -f $(SOURCE).pdf
organized:
#rm -f $(foreach postfix, $(EXTENSIONS), $(SOURCE).$(postfix))
#rm -f ./*~
#cd ./tex && rm -rf $(foreach postfix, $(EXTENSIONS), *.$(postfix)) && rm -f ./*~
Once you start your process you have to store the process id (pid) to a file, let me call it evince.PID. So change your line in:
$(PDFREADER) $(SOURCE).pdf & echo $$! > evince.PID
This saves the pid in the evince.PID file. To stop the previous process just read the pid from that file (if exists) and kill the corresponding process. To do this add to you makefile:
if [ -a evince.PID ]; then \
kill -TERM $$(cat evince.PID) || true; \
fi;
For future makefile/bash writing notice that:
$$! corresponds to the bash variable $!, as the makefile syntax also indicates variables with $ to disambiguate a bash variable we need a double $$
$$(cat evince.PID) reads the file into a bash variable, again marked with $$
kill -TERM returns a non 0 exit code if the process does not exist (e.g. you already killed it by hand). With || true a 0 exit code is returned even if kill failed, so a failed kill does not cause the makefile to fail
Edit:
My bad, I figured out that -a to check if a file exists is now deprecated and should be avoided in favor of -e. Debian Almquist shell (dash) seems to be a bit picky about this. To kill the process then use:
if [ -e evince.PID ]; then \
kill -TERM $$(cat evince.PID) || true; \
fi;
I get an error (on line: sh up.sh) running the following:
#!/bin/bash
# Install angular components
echo "Installing Angular Components..."
cd angApp
npm install
# Install Server components
echo "Installing Backend Components..."
cd ..
cd APIServer
# go back to main dir
cd ..
# ask to see if we should launch server
echo "Do you want to launch the server now? Enter (yes/no) "
read shouldLaunch
# Launch if requested. Otherwise end build
if [ "$shouldLaunch" == "yes" ]; then
echo "Great! Launching the servers for you..."
sh up.sh
else
echo "No problem..."
echo "you can launch the server by doing ./up.sh"
echo "bye!"
fi
How do I run the up.sh script?
If the up.sh file is in the same directory as the file containing the code above then you can do
echo "Great! Launching the servers for you..."
$(dirname $0)/up.sh
The variable $0 is the path of the current script, dirname strips off the last segment of the path, and $(...) turns the output of dirname into a string.
To avoid cd-ing mess, simply run the parts in subshells, like:
#!/bin/bash
(
# Install angular components - in shubshell
echo "Installing Angular Components..."
cd angApp
npm install
)
(
# Install Server components - again in subshell
echo "Installing Backend Components..."
cd APIServer
#do something here
)
# go back to main dir
#cd .. #not needed, you're now in the parent shell...
# ask to see if we should launch server
echo "Do you want to launch the server now? Enter (yes/no) "
read shouldLaunch
# Launch if requested. Otherwise end build
if [ "$shouldLaunch" == "yes" ]; then
echo "Great! Launching the servers for you..."
sh up.sh
else
echo "No problem..."
echo "you can launch the server by doing ./up.sh"
echo "bye!"
fi
Writing a script to automate my flask environment setup.
if [[ -z $1 ]];
then
echo "usage: flaskup <dirname> <template dir>";
exit
else
virtualenv $1 &&
cd ./$1 &&
source bin/activate &&
bin/pip install flask &&
mkdir ./app &&
mkdir ./app/static &&
mkdir ./app/templates &&
exit;
fi
I'm expecting this to leave me in the directory it created, with the virtual environment activated, however it leaves me in the same directory I ran the script from. What can I do to make the script exit with the shell in the activated virtual environment?
If you run the script in its own shell (run it as /path/to/script or script if it lives in your $PATH) then you can't get what you want. The shell that runs the script is a different shell then the one you ran it from and it cannot change the status of the parent shell. The closest you could do would be to have the script echo the path as output and run it as cd "$(/path/to/script)" or similar.
Alternatively, if you run the script as . /path/to/script (or similar) then you are running it with your current shell and any directory changes it makes will be happening in your current shell and not a sub-shell.
I am very new to Makefiles, so I am probably not doing this the best way (your input is much appreciated, since I would like to learn how/why mine is bad). Anyway, here is my problem:
I have a Daemon that I wrote for a program of mine and I am trying to install it with the Makefile (target is "install"). What the "install" target is supposed to do is move the daemon binary to a location, then move the "service script" to either /etc/init.d/ or /etc/rc.d/ (since different distros have different folders...). Here is my makefile so far:
all:
#echo "Making Components"
#cd Daemon; make
#echo "Components Built"
install:
#echo "Installing Components"
#mkdir -p /usr/lib/
#cp Daemon/myprog_d /usr/lib/myprog_d
-#test -d /etc/init.d && cp Scripts/myprog /etc/init.d/
-#test -d /etc/rc.d && cp Scripts/myprog /etc/rc.d/
-#test ! -d /etc/init.d -a ! -d /etc/rc.d && echo " Warning: Couldn't install script. Manually install Scripts/myprog"
#mkdir -p /var/log/
#echo "Installed."
uninstall:
#echo "Uninstalling Components"
#./Scripts/myprog stop > /dev/null
#rm -f /usr/lib/myprog_d
#echo "Uninstall complete"
clean:
#echo "Cleaning Components"
#cd Daemon; make clean
#echo "Clean complete"
As you can see, the "install" target tests to see if those two directories exist and, if they do, copies the script into them (I haven't yet done it to "uninstall", don't worry).
My first question: Is this the right way to do this? The "all" and "clean" targets work (there is another makefile in "Daemon/", as you can deduce), but I want to know if there is a cleaner way of doing this.
Secondly, because the "test" function returns non-zero, I had to do "-" before it so the error would be ignored. Unfortunately, that results in the "make install" output being:
Installing Components
make: [install] Error 1 (ignored)
make: [install] Error 1 (ignored)
Installed.
Which is very ugly and probably not good practice. What can I do in this case? (I have tried both -# and #-, but # will not suppress the "ignored" output)
Sincerely,
Chris
I'd do it this way:
#if [ -d /etc/init.d ]; then cp Scripts/myprog /etc/init.d/ ; fi
#if [ -d /etc/rc.d ]; then cp Scripts/myprog /etc/rc.d/ ; fi
And I'm a little confused by your next line (-#test ! -d /etc/init.d -a !...) but you can probably do it the same way.
That takes care of the error messages, but if you wanted to keep the makefile as it is, you could suppress them by running make -s.