0

I think this is related to: How can I check if a program exists from a Bash script?

Specifically, I want to run py -m http.server on computers that have py but don't have python3 and I want to run python3 -m http.server on computers that have python3 but not py. I also tried just checking the version number: py -v && py -m http.server; python3 -v && python3 -m http.server but this still seems to have the same problem, and hitting ctrl+C twenty times doesn't kill it.

I tried py && py -m http.server; python3 && python3 -m http.server but I believe it's executing the second command within python. Also, there are other aliases for Python on other computers. I know that I could just set py as an alias for python3, but I'm looking for a universal solution.

(Side note: It really bothers me that this is inconsistent. They should all just work.)

Eventually, I want a script that runs two things in parallel: the first is just npm run dev which has a --watch on it and has to continue to run, and the other is to cd docs/ then use python to host on localhost, then open chrome to localhost:8000, additional help would be much appreciated, still a beginner to Linux.

I also want to make a second command that runs npm run build, changes the second line in docs/sw.js from const dynamicCacheName = 'site-dynamic-vNUMBER'; to replace NUMBER with NUMBER+1.

wjandrea
  • 28,235
  • 9
  • 60
  • 81
Justin
  • 945
  • 12
  • 26
  • What scripting language are you targeting? For Bash, add the [tag:bash] tag. For generic shell, add the [tag:shell] tag. – wjandrea Feb 06 '21 at 22:29
  • I'm not sure if it's bash or shell to be honest, I'll have to look into that (sorry I'm not good at this type of stuff). Do shebangs basically set all of them as the same alias so I can just call one? – Justin Feb 06 '21 at 22:51
  • OK, I added the shell tag, since it's generic. Ignore the comment about shebangs; I misunderstood what you're doing. – wjandrea Feb 06 '21 at 22:55

3 Answers3

1

Does this do what you're after? Assuming bash or similar:

( py -V && py -m http.server ) || ( python3 -V && python3 -m http.server )

On my box this does the following:

$ ( py -V && py -m http.server ) || ( python3 -V && python3 -m http.server )
py: command not found
Python 3.5.2
Serving HTTP on 0.0.0.0 port 8000 ...
tink
  • 14,342
  • 4
  • 46
  • 50
  • Although if `py -m http.server` returns false (like if it's killed), then the second part will run anyway. – wjandrea Feb 06 '21 at 22:44
  • 1
    fair comment ... one could capture return codes for both `-V` variants and then pick the existing/preferred one ... I was just building on his own approach. – tink Feb 06 '21 at 22:46
  • `( py -V && py -m http.server ) || ( python3 -V && python3 -m http.server )` seems to be what I was after, thank you! Do you know how to run two processes in parallel by chance? I know `&&` is for if the first succeeds, `||` is for if the first fails, and `;` is run after regardless, but I want them to run in parallel. Anyway, I'll mark this as the answer since it answered my primary question, thank you. – Justin Feb 06 '21 at 22:48
  • `( py -V && py -m http.server& ) ; ( python3 -V && python3 -m http.server& )` ... not sure about "run in parallel", though; as soon as one has grabbed the port the other will fail ... – tink Feb 06 '21 at 22:59
  • I mean run in parallel for something else. I now have `build` and `localhost` as npm commands, and I'd like to be able to run them at the same time, but currently only one runs: `"build": "cross-env NODE_ENV=production postcss src/styles.css -o docs/css/styles.css && cleancss -o docs/css/styles.css docs/css/styles.css", "localhost": "cd docs && ( py -V && py -m http.server ) || ( python3 -V && python3 -m http.server )", "local-dev": "npm run dev && npm run localhost"` – Justin Feb 06 '21 at 23:07
0

For the second part of your question you could have a small bash script like this (I included the python or py check):

#!/bin/bash

npm run dev --watch &

chromium-browser "http://localhost:8000" 2>/dev/null &

cd docs/ || exit # Exit if the cd command fails
if command -v py -V &> /dev/null; then
    echo "py"
    py -m http.server
elif command -v python3 -V &> /dev/null; then
    echo "python3"
    python3 -m http.server
else
    echo "Neither command found"
fi

& At the end of a command will run it in the background, as written above it will still display the output of the commands.

If you kill the script with CTRL+C it will kill everything, chromium, the python server and the npm run.

Paul
  • 305
  • 1
  • 7
  • Ooh this looks awesome, thank you, I'll test it right now. So I save it as a `.sh` file then run `sh myfile.sh`? I was just trying `npm run dev & npm run localhost` but after CTRL+C I wasn't able to kill node in the background, even with `sudo pkill node` and `sudo killall node` it still shows up in `ps` – Justin Feb 06 '21 at 23:22
  • It's in bash (as you can see in the first line), so `bash myfile.sh`. To kill your node process you need to get its pid using `ps -ef` and use `kill PID` – Paul Feb 06 '21 at 23:26
  • Ah got it. What's the difference between bash and sh? I ran it with `bash myfile.sh` and it ran, but the `npm run dev` part isn't going in the background. Both commands need to continue running. – Justin Feb 06 '21 at 23:28
  • Still cannot kill `node`: https://imgur.com/a/1rdpIbC – Justin Feb 06 '21 at 23:29
  • [bash vs sh](https://stackoverflow.com/questions/5725296/difference-between-sh-and-bash) I think It's worth the read if you begin ! You can try `kill -9 PID` (-9 I used to send a more "violent" signal to the process to tell it to stop). I edited my post with a script slightly simpler. – Paul Feb 06 '21 at 23:47
  • `chromium-browser`, `chrome`, `google-chrome`, `open`, and `chromium` are all `command not found`, can't seem to open chrome from command line from your answer or any of these: https://stackoverflow.com/questions/28162697/how-can-i-open-google-chrome-from-the-terminal-with-the-url-localhost3000 – Justin Feb 07 '21 at 00:07
  • It's probably not installed, you can install chromium from command line using `apt install chromium-browser` or `dnf install chromium` depending on your distribution. You can also use an other browser if you want. – Paul Feb 07 '21 at 00:12
  • 1
    Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/228361/discussion-between-paul-and-justin). – Paul Feb 07 '21 at 00:22
0

I actually wanted to post a full answer since I got what I was after from several answers and comments and chatting with a friend:

I installed the npm package concurrently and then added a local-dev npm script in my package.json:

"scripts": {
    "dev-no-watch": "postcss src/styles.css -o docs/css/styles.css",
    "dev": "postcss src/styles.css -o docs/css/styles.css --watch --verbose",
    "build": "cross-env NODE_ENV=production postcss src/styles.css -o docs/css/styles.css && cleancss -o docs/css/styles.css docs/css/styles.css",
    "localhost": "cd docs && ( py -V && py -m http.server ) || ( python3 -V && python3 -m http.server )",
    "local-dev": "concurrently --kill-others \"npm run dev\" \"npm run localhost\""
},

Which runs both concurrently, and upon hitting ctrl+C, kills both as well.

I of course added localhost from the answer for the original question of detecting python version and running it correctly/failing gracefully, etc, and that works like a charm.

Hope this answer is helpful to someone in the future : )

(Now I just need to find out hos to edit a line of a file from the command line OS independently)

Justin
  • 945
  • 12
  • 26