Вопрос или проблема
Я работаю на системе Mac 15.1 и открываю соединение с jumpserver, чтобы иметь возможность подключаться к нескольким другим серверам. Обычно скрипт работает прекрасно, но иногда он зависает, и ничто, кроме полной перезагрузки моего Mac, не помогает снова открыть привязанные порты. Я использую iTerm2 в качестве терминала на Mac OS 15.1.
Вот скрипт:
#!/bin/sh
username="myusername"
jumpServer="vl-com-jfd-p01.example.com"
# shellcheck disable=SC2039
hosts=("gl-d-foo.d.gcp.example.com" "192.168.0.234" "vl-web-int-d02" "10.40.13.44" "172.16.20.88" "10.245.131.226" "gl-p-foo.p.gcp.example.com" )
destSshPort=22
destMysqlPort=3306
x=10021
y=10022
for i in "${hosts[@]}"; do
:
server=$i
sshTunnel="$sshTunnel -L $x:$server:$destMysqlPort -L $y:$server:$destSshPort"
echo "Сервер: $server -- MYSQL: $x -- SSH: $y"
x=$((x + 2))
y=$((y + 2))
done
if [ -z "$sshTunnel" ]
then
echo "ssh туннели пусты"
else
ssh $sshTunnel $username@$jumpServer
fi
После вызова этого скрипта и успешного подключения к jumpserver я открываю второй терминал и подключаюсь к одному из серверов, вводя что-то вроде этого:
ssh -p10022 -L 9994:10.239.244.31:3306 myusername@localhost
Все это работает хорошо, так что с самим скриптом ничего не так.
Но иногда я теряю соединение с jumpserver, и после повторного запуска процесса я получаю сообщения, вроде:
bind [127.0.0.1]:10021: Адрес уже используется channel_setup_fwd_listener_tcpip: не удается прослушать порт: 10021
Даже после закрытия iTerm2 и его повторного запуска.
Итак, вот мой вопрос:
как я могу освободить порты, не перезагружая Mac или ожидая, пока они закроются сами?
Есть ли какая-нибудь команда, с помощью которой я могу вручную закрыть порты?
Благодаря комментарию от @Gordon Davisson я смог решить свою проблему. Она снова возникла после сбоя iTerm2 после обновления.
$ netstat -an -f inet | grep 10021
tcp4 0 0 127.0.0.1.10021 *.* LISTEN
Так что я взглянул на результаты ps
:
$ ps
PID TTY TIME CMD
1747 ttys004 0:00.03 -bash
1807 ttys005 0:00.03 -bash
2030 ttys006 0:00.03 -bash
2096 ttys007 0:00.06 -bash
78235 ttys007 1:59.37 ssh -p10022 -L 9994:10.239.244.31:3306 p325111@localhost
2162 ttys008 0:00.05 -bash
68850 ttys008 0:01.69 ssh -p10022 -R 9003:127.0.0.1:9003 p325111@localhost
2231 ttys009 0:00.07 -bash
68834 ttys009 0:00.01 /bin/sh ./tunnel.sh
68835 ttys009 4:35.26 ssh -L 10021:foo.d.example.com:3306 -L 10022:foo.d.gcp.puc-mobile.de:22 -L 10023:192.168.0.234
77772 ttys010 0:00.13 -bash
82148 ttys011 0:00.02 -bash
82314 ttys014 0:00.02 -bash
82386 ttys015 0:00.02 -bash
82446 ttys016 0:00.03 -bash
82515 ttys017 0:00.03 -bash
82653 ttys017 0:00.01 /bin/sh ./tunnel.sh
82654 ttys017 0:00.08 ssh -L 10021:foo.d.gcp.puc-mobile.de:3306 -L 10022:foo.d.gcp.puc-mobile.de:22 -L 10023:192.168.0.234
После завершения обоих процессов, которые содержали 10021, в моем случае 68835 и 82654, я смог снова запустить свое соединение, и все порты стали доступны. Так просто!
Ответ или решение
Закрытие SSH-портов или привязок портов вручную может быть необходимым в ситуациях, когда удаленная сессия завершилась некорректно, и порт остается занят, что мешает дальнейшей работе. Это распространённая проблема, особенно в средах с использованием SSH-туннелей, как в вашем сценарии с macOS 15.1 и iTerm2. В этом ответе мы подробно рассмотрим, как освободить заблокированные порты без необходимости перезагрузки компьютера.
Шаг 1: Определение занятых портов
Для начала, вам необходимо узнать, какие порты заняты. Узнать это можно с помощью команды netstat
, которая отображает текущие сетевые подключения. Запустите в терминале следующую команду:
netstat -an -f inet | grep 10021
Эта команда фильтрует результаты netstat
, показывая состояние порта 10021, который, судя по вашему описанию, может быть занятым. Если вы видите строку с LISTEN
, это означает, что порт уже занят каким-то процессом.
Шаг 2: Найдите PID процесса
Чтобы выяснить, какой процесс использует порт, вам необходимо получить его идентификатор (PID). Запустите команду:
lsof -i TCP:10021
Эта команда покажет все процессы, использующие указанный порт, вместе с их PID. Обратите внимание на идентификаторы процессов, которые будут в выводе команды.
Шаг 3: Закрытие процесса
Теперь, зная PID процесса, который занимает порт, вы можете завершить его с помощью команды kill
. Допустим, вы нашли, что PID процесса, занимающего 10021, равен 68835. Для его завершения выполните:
kill 68835
Если процесс не завершился, можно использовать более "агрессивный" метод:
kill -9 68835
comЗапомните, что использование kill -9
убивает процесс без возможности сохранения данных, поэтому это должно использоваться только в крайних случаях.
Шаг 4: Проверка освобождения порта
После завершения процесса проверьте снова, освободился ли порт, повторив команду netstat
:
netstat -an -f inet | grep 10021
Если вывод не содержит строки с LISTEN
, это означает, что порт успешно освобожден и вы можете заново запустить свой скрипт SSH.
Заключение
Закрытие портов в macOS через SSH — это простой процесс, который может значительно упростить вашу работу. Вы всего лишь должны следовать четырём шагам: определить занятые порты, найти PID процесса, завершить соответствующий процесс и проверить освобождение порта. Надеемся, что эта информация сделает вашу работу с SSH-туннелями более стабильной и надежной.