Check unused ports in a given range and assign an open one

Hi. I need to add code to my KSH script to automatically assign an open port number from a pre-defined range to an Oracle listener.

Should I use:

lsof -i

or

netstat -vatn

or something else?

Thanks.

Managing Oracle Database Port Numbers

Indicates that oracle does this already. So, if you need to use a range of ports that is not a default, you would have to reconfigure oracle port management. First. Then what you describe will occur automatically without your intervention.

Hi Jim. I'd better give a bit more info. I'm generating a new listener file for a gateway from a script so I have to assign a port. There will be multiple listeners running on different ports on that same host. If I choose one that's already in use the new listener obviously won't start. The range I'll choose this from is not the important part, I'll simply stick to the default range defined for Oracle. I just need to know the best way to determine if the port I choose is in use already. Thanks.

---------- Post updated at 11:53 AM ---------- Previous update was at 10:42 AM ----------

So this should work, right? Or am I missing something?

PORT=$(($RANDOM%50+1521))
RC=$(netstat -vatn | grep $PORT)
[[ -z $RC  ] ] && print "Port is free"

You need a few changes in your script:

PORT=$(($RANDOM%50+1521))
RC=$(netstat -vatn | grep $PORT)
[[ -z  "$RC" ]] && print "Port is free"

or

PORT=$(($RANDOM%50+1521))
netstat -vatn | grep $PORT &&  echo "Port is free"

I just do not see why you are doing this manually, but whatever. If you have issues, consider this port selection something to check first.

1 Like

Probably a daft question, but if you are starting a process to listen on a port, how will the client know which port to connect to?

Apologies for being daft ..... :o

Robin

Because I'm creating the related tnsnames entry on the DB host at the same time. It's all automated through a GUI with the push of a button. Everything has to be done for the end user who knows nothing about Oracle.

@Jim, that's also why it's not done manually. My script has to choose a free port on a specified host in order to create a new listener file from scratch and then start it. There will be multiple listeners running simultaneously and each has to have it's own unique port. Hope that clarifies it.

Can I assume that you are publishing tnsnames.ora so that anyone can read it? If so, why are you wanting to set up a listener on a new port?

The Oracle listener can support connections to multiple databases on the same host, all using the default port 1521. The database is coded in the connection request from the client whether you use the default port or any other port, unless your listener has a 'default if not specified' type definition. It would seem far better to use the listener and add connection details for each database. That way, the client never needs to worry about finding out which port to connect on, it just specifies the database name.

What am I missing here? If you are after hardening your server so that an intruder doesn't know which port to attack, then you have the same problem for your clients in that they will have to have a way to find out.

Can you explain the reasons why you want multiple listening processes? After the connection is established, the listener keeps out the way of the communication, so it's not a bottleneck to performance.

Thanks, in advance,
Robin

Hi Robin. These aren't database listeners. As mentioned earlier, they're gateway listeners and a listener for MSSQL has to be configured differently to one for say DRDA. They cannot be shared.

I don't see MSSQL mentioned earlier and I missed the point about them being Gateway as opposed to plain database listeners, but how about this suggestion:-

  • Select a range of ports that are free
  • Define them in /etc/services quoting the database name (DA, DB, DC, DD etc.)
  • As the listener starts, it reads /etc/services and starts on a fixed port number, reporting failures however you choose, e.g. syslog, email, sms, console, 3rd party tools etc.

That way you know the ports should be allocated to just your service. If you start them at boot, then one would think that they should still be free. if something else is grabbing one, then find out why and/or change /etc/services to move your service to a new port. It's not foolproof because not everything respects /etc/services but it's a good place to start and many network tools (e.g. netstat & lsof) do, making their output more meaningful.

You could even (if your databases are using a sequential naming system) make the port numbers obvious and predictable, e.g. DA is port 13001, DB is port 13002, etc. This would give your clients wanting to connect a consistent port to connect to.

Would that help?

Robin

1 Like

MSQL or DRDA are just examples of some of the gateways I'm using so there was no actual need to mention them specifically. The range of free ports is defined initially and they're reserved for Oracle. I just have to assign a new one when creating the gateway listener file so I'll just use netstat for that. Your point about making port numbers more obvious is a sensible approach. I'll modify my script slightly to assign ports from that defined range incrementally if possible. Thanks for your advice.