maxheld83 / byod

make life easier with r projects and docker
MIT License
0 stars 0 forks source link

shell script should automatically use empty port #1

Open maxheld83 opened 5 years ago

maxheld83 commented 5 years ago

if, for example, other docker image occupies 8787

Ch1pzZz commented 5 years ago

stefanobaghino on stackexchange wrote this: One-liner I've put together a nice one-liner that quickly serves the purpose, allowing to grab an arbitrary number of ports in an arbitrary range (here it's divided in 4 lines for readability): comm -23 \ <(seq "$FROM" "$TO" | sort) \ <(ss -tan | awk '{print $4}' | cut -d':' -f2 | grep '[0-9]{1,5}' | sort -u) \ | shuf | head -n "$HOWMANY" Line by line comm is a utility that compares lines in two files that must appear sorted alphabetically. It outputs three columns: lines that appear only in the first file, lines that only appear in the second one and common lines. By specifying -23 we suppress the latter columns and only keep the first one. We can use this to obtain the difference of two sets, expressed as a sequence of text lines. I learned about comm here. The first file is the range of ports that we can select from. seq produces a sorted sequence of numbers from $FROM to $TO. The result is sorted alphabetically (instead of numerically) and piped to comm as the first file using process substitution. The second file is the sorted list of ports, that we obtain by calling the ss command (with -t meaning TCP ports, -a meaning all - established and listening - and -n numeric - don't try to resolve, say, 22 to ssh). We then pick only the fourth column with awk, which contains the local address and port. We use cut to split address and port with the : delimiter and keep only the latter (-f2). ss also output an header, that we get rid of by grepping for non-empty sequences of numbers that are no longer than 5. We then comply with comm's requirement by sorting without duplicates -u. Now we have a sorted list of open ports, that we can shuffle to then grab the first "$HOWMANY" ones with head -n. Example Grab the three random open ports in the private range (49152-65535) comm -23 <(seq 49152 65535 | sort) <(ss -tan | awk '{print $4}' | cut -d':' -f2 | grep "[0-9]{1,5}" | sort -u) | shuf | head -n 3 could return for example 54930 57937 51399 Notes switch -t with -u in ss to get free UDP ports instead. replace shuf with sort -n if you prefer to get available ports numerically sorted instead of at random

I think this could work right? I am not sure however how to implement this in the code, as I can only assume the code does what he says it does >< @maxheld83 do you thiink that would be an option? seems like a lot of effort to use more than this "one" line. The other solutions I found were (at least seemingly) more complicated with longer code-bits.

Ch1pzZz commented 5 years ago

https://unix.stackexchange.com/questions/55913/whats-the-easiest-way-to-find-an-unused-local-port this is the URL. forgot to add in the comment before

maxheld83 commented 5 years ago

This is a good resource that you found there. I think our first bet should be to try and let the kernel assign an empty port, which is what some of the answers there suggest. That apparently can be done by just passing 0 as the port, and ideally kernel will then assign an empty one.

You can try this out by simply editing the launch.sh in this repo. This file consists of a (fairly long) docker command, and one of them binds the container and host port numbers, currently:

--publish=8787:8787  `# port mapping, host left, cont right`\

It might be worth trying this out with 0 for the host, though then we have to figure out a way to capture whatever the host has assigned.

It's also possible that docker comes with some special bells/whistles or limitations to keep in mind here; that might be worth researching as well: whether docker run can automatically map to an empty port on the host.

More on that might be found here:

If all of this leads nowhere and we figure out that docker run really really needs the host port to begin with, then some of the above solutions in the s-e post might be a good way to start, and they could just become part of the launch.sh script.

However, it's always better to use system/existing tooling for this kind of stuff if it exists.