Search code examples
linuxshellserveryamlsh

How to start fastapi ,react, node server using shell script file


I need to run many commands one by one to start my project instead of that i tried to put commands on shell script file

server.sh

#!/bin/bash
sudo systemctl start elasticsearch.service
sudo systemctl start kibana.service
cd fastapi
uvicorn main:app --reload --port 8000
cd ..
cd reactjs
npm i 
npm start
cd ..
cd node
npm i 
npm run dev

These are commands I put it in a .sh file, now problem is after uvicorn main:app --reload --port 8000 this command sh files failed to execute rest of the commands.

how to resolve this using .sh file or yaml file


Solution

  • You must run in background the three main scripts in your code:

    uvicorn main:app --reload --port 8000 &

    npm start &

    npm run dev &

    That & is used after a command to run this one in background, so the script will not stop in the first command (avicorn) and it will follow with the code.

    And because of those commands will generate an output in the terminal (in the case you are running them from it) that output can be confused, so I would recommend redirect the output to a file for every command you run in background.

    Your code could be like this:

    #!/bin/bash
    
    sudo systemctl start elasticsearch.service
    sudo systemctl start kibana.service
    cd fastapi
    uvicorn main:app --reload --port 8000 > uvicorn.log &
    cd ../reactjs
    npm i
    npm start > npmstart.log &
    cd ../node
    npm i 
    npm run dev > npmdev.log &
    

    For killing those process you should use the kill command. There are several options for killing, you can visit kill signals on Linux to understand how it works. Or if you want to use a GUI, the system monitor might work, but you must know what PID is what you want to kill.

    When a process starts this saves in $! its current PID (process ID), so you can use the next statement to show the PID:

    echo $!

    And when you want to kill the process, use:

    kill -9 the_pid_shown_with_echo

    So your code could be like this (but it's not enough in this case):

     #!/bin/bash
    
    sudo systemctl start elasticsearch.service
    sudo systemctl start kibana.service
    cd fastapi
    uvicorn main:app --reload --port 8000 > uvicorn.log &
    echo "Uvicorn ID: $!" | tee uvicornpid.txt
    cd ../reactjs
    npm i
    npm start > npmstart.log &
    echo "npm start ID: $!" | tee npmstart.txt
    cd ../node
    npm i 
    npm run dev > npmdev.log &
    echo "npm run dev ID: $!" | tee npmrundev.txt
    

    The statements with tee command like echo "Uvicorn ID: $!" | tee uvicornpid.txt are used for showing the text in the terminal and also redirect the output to a file. So you can check those files later for checking the PID's

    But as I said, in this case this is not enough because unless with node this runs various process and if you kill the process by using the PID you got with $! this will kill that process (and maybe other one). But the process which is listening in that port, will stay running and when you run the app again, this will crash because the port is in use (unless you run the app in another port, but I would not recommend it).

    You can use several commands for getting the PID you should kill. The first way is using commands like:

    pgrep node

    This will return all PID which match with node word

    ps -efl | grep -E "(node|PID)"

    This will return an output with several columns and you will can see the PID of all process which match with node word and another information that might be useful.

    Other useful commands the might be better for you are these:

    lsof -i :4000

    This will return the process running in the 4000 port (you will get the PID, the name of the process and more information)

    fuser 4000/tcp

    This only will return 4000/tcp and the PID of the process running in that port.

    So, once you get the PID with one of those methods, you should kill the process with the kill command as I explained before.