В настоящее время Python считается зрелым языком программирования, который широко используется специалистами по обработке данных и инженерами по искусственному интеллекту (ИИ) из-за его простоты и легкочитаемого синтаксиса.
В данном руководстве мы обсудим [Errno 32] Broken pipe в Python, известное сообщение об ошибке, которое мы часто видим при взаимодействии с файловой системой. Мы разберем причину ее возникновения, а также способы ее избежать и исправить в коде.
«Сломанный канал» обычно считается ошибкой IOError (сокращение от «Ошибка ввода-вывода»), которая произошла на уровне системы Linux. Обычно она возникает при чтении и записи файлов или, другими словами, при выполнении ввода / вывода файлов или сетевого ввода / вывода (через сокеты).
Эквивалентная системная ошибка Linux – EPIPE, взятая из кодов ошибок GNU libc.
Макрос: int EPIPE
“Broken pipe.” означает, что на другом конце конвейера нет считывания процесса. Каждая функция библиотеки, вызывающая код ошибки, также выдает сигнал SIGPIPE; этот сигнал завершает программу, если не обрабатывается или не блокируется. Следовательно, программа никогда не отобразит EPIPE до тех пор, пока она не обработает или не заблокирует SIGPIPE.
Из приведенного выше утверждения мы можем сделать вывод, что система, отправляющая сигнал SIGPIPE, вызывает ошибку [Errno 32] Broken pipe в механизме межпроцессного взаимодействия Linux.
Например, система Linux внутренне использует другой сигнал, называемый SIGINT. В Linux команда Ctrl + C отправит сигнал SIGINT, чтобы завершить процесс, или мы можем использовать команду kill для достижения того же эффекта.
Python по умолчанию не игнорирует SIGPIPE. Однако он преобразует сигнал в исключение и вызывает ошибку – IOError: [Errno 32] Сломанный канал каждый раз, когда он получает SIGPIPE.
Ошибка “сломанный канал” при подключении к терминалу Linux
Всякий раз, когда мы сталкиваемся с ошибкой [Errno 32] Broken pipe при попытке передать вывод скрипта Python другой программе, например:
$ python file_name.py | head
Объяснение:
Вышеупомянутый синтаксис конвейера создаст процесс, отправляющий данные в восходящем направлении, и процесс, читающий данные в нисходящем направлении. Когда нисходящему потоку не нужно читать данные восходящего потока, он отправит сигнал SIGPIPE процессу восходящего потока.
Когда нисходящий поток не должен читать данные восходящего потока? Давайте разберемся в этом на примере. Команда head в этом примере должна прочитать достаточно строк, чтобы сообщить восходящему потоку, что нам больше не нужно его читать, и она отправит сигнал SIGPIPE процессу восходящего потока.
Всякий раз, когда восходящий процесс является программой Python, возникает ошибка типа IOError: [Errno 32] Broken pipe.
Как избежать ошибки “сломанный канал”?
Если мы не заботимся о правильном перехвате SIGPIPE и нам нужно быстро запустить процесс, вставьте следующий фрагмент кода в начало программы Python.
Синтаксис:
from signal import signal, SIGPIPE, SIG_DFL #Ignore SIG_PIPE and don't throw exceptions on it...(http://docs.python.org/library/signal.html) signal(SIGPIPE,SIG_DFL)
Объяснение:
В приведенном выше фрагменте кода мы перенаправили сигналы SIGPIPE на стандартный SIG_DFL, который система обычно игнорирует.
Однако рекомендуется остерегаться руководства Python по библиотеке сигналов, чтобы предостеречь от такой обработки SIGPIPE.
Перехват IOError во избежание ошибки Broken pipe
Поскольку ошибка Broken pipe является ошибкой IOError, мы можем разместить блок try / catch, чтобы ее перехватить, как показано в следующем фрагменте кода:
Синтаксис:
import sys, errno try: ### IO operation ### except IOError as e: if e.errno == errno.EPIPE: ### Handle the error ###
Объяснение:
В приведенном выше фрагменте кода мы импортировали модуль sys и errno и разместили блок try / catch, чтобы перехватить возникшее исключение и обработать его.
Возможное решение проблемы в многопроцессорной программе
В программах, которые используют рабочие процессы для ускорения обработки и многоядерные процессоры, мы можем попытаться уменьшить количество рабочих процессов, чтобы проверить, сохраняется ли ошибка или нет.
Большое количество рабочих процессов может конфликтовать друг с другом при попытке взять под контроль ресурсы системы или разрешение на запись на диск.
Изучаю Python вместе с вами, читаю, собираю и записываю информацию опытных программистов.
Updated on 5/5/2022 – Have you ever encountered a situation in which you were unable to download any package on your Linux machine ? Or you might have probably seen an error like package not installed? This kind of error can easily be fixed with a command like “sudo apt install –f”. On rare occasions, you may have experienced a broken pipe error.
A pipe in Linux / Unix connects two processes, one of them has read-end of the file and the other one has the write-end of the file. When a process writes to a Pipe, it gets stored in a buffer and gets retrieved by the other process. Broken pipe occurs when a process prematurely exits from either end and the other process has not yet closed the pipe.
Example use case:
A user has just recently reinstalled RVM (Ruby Version Manager) after he performed a fresh install of Ubuntu.
He then opened up the terminal and issued the command:
type rvm | head -1
This issued the following error:
rvm is a function -bash: type: write error: Broken pipe
What happened here is that when the user runs the command type rvm | head -1, bash has actually executed type rvm in one process and head -1 in another process. The stdout of the type part is connected to the “write” end of a pipe whereas the stdin of the head part is hooked up to the “read” end. Note that the two processes have run concurrently ( at the same time ).
The head -1 process has carried out a read operation of data from stdin , then prints out a single line (as dictated by the -1 option) before exiting, causing therefore the “read” end of the pipe to be closed. Since the rvm function has quite a long data stream (about 11 kB after having been bash parsed and reconstructed), which means that head exits yet at the same time type still has some data to write out (few KB).
Since type is trying to carry out a write operation to a pipe whose other end has therefore been closed – a brokenpipe routine or the write() function that it invoked, will return an EPIPE error which is known as “Broken pipe”.
Inspecting the Command
In most cases, this might not be the case but the first step you should check is whether the command issued was right or not. You should reissue the command and check whether it gets executed or not. You can also try issuing commands like “sudo apt update” and “sudo apt install –f” as these commands are not destructive in nature. If your problem still persists, try rebooting the machine and see whether the problem was resolved or not.
Fixing a Problem with File System
When you have issued the commands mentioned earlier multiple times and you still get the error, check whether the error reads something like “read-only file system” in the terminal output. This may be caused when your boot partition gets mounted as read-only for some reason. The problem could be caused by some faulty software installation when the system decides that it is not safe to write to the drive.
Read: How to create a Sudo user on Ubuntu
The other cause might be when you try to install something from apt and the installer needs to access some resource in read mode, but cannot perform the read operation properly. It may throw an error like “sudo: cannot mount”. This error occurs because most of the ‘entities’ in Linux are files and in order to read a resource, Linux would need to open that file and read it. If however another process is currently using that resource, then it may not be possible to read the file. Also, when the reading process exits abruptly and does not close the file, it may corrupt the file until the next boot.
If you still cannot access the files even after rebooting, then the problem could be bigger than anticipated. You may have a broken file system. To resolve this issue, you may need a stable Linux environment in order to work on the broken system. The best way to do this is to boot from a Live Linux USB drive and work from it.
This is the right moment to backup all your data. Although the following steps are safe, you should make sure to store your data on a secure device.
Once you boot into a Live USB drive you should start to check for the partitions with a corrupt file system. To do so, issue the following command:
sudo fsck.ext4 -fv /dev/sdaX”
Note that here X stands for the partition that you are trying to scan. Note that this command is for partitions of type ext4. If you have a partition of type ext3 or ext2 you will need to replace the command with “fsck.ext3” and “fsck.ext2” respectively. This will scan your drive and print the output on the terminal (note the -v flag). Alternatively, you can specify a -c flag to surface-scan the drive; it will look for bad sectors on the drive.
Once you have done this, your partition should hopefully been fixed. Now Boot into your machine and issue the command:
sudo mount -o rw,remount /
This will restore the read/write permission on your drive and will therefore solve the broken pipe issue.
Read: How to manage permissions in Linux : guide for beginners
Afterwords
You have just seen one solution to resolve the broken pipe issue, but a broken pipe is not a problem, it could be a symptom of a larger problem more often than not. You can have a broken pipe whenever you are trying to read a stream like resource that gets closed prematurely..
If you like the content, we would appreciate your support by buying us a coffee. Thank you so much for your visit and support.
Sometimes my SSH session disconnects with a Write failed: Broken pipe
message. What does it mean? And how can I keep my session open?
I know about screen
, but that’s not the answer I’m looking for. I think this is a sshd
config option.
asked Sep 14, 2010 at 9:04
Peter StuifzandPeter Stuifzand
1,8512 gold badges12 silver badges7 bronze badges
It’s possible that your server closes connections that are idle for too long.
You can update either your client (ServerAliveInterval
) or your server (ClientAliveInterval
)
ServerAliveInterval
Sets a timeout interval in seconds after which if no data has
been received from the server, ssh(1) will send a message through
the encrypted channel to request a response from the server. The
default is 0, indicating that these messages will not be sent to
the server. This option applies to protocol version 2 only.
ClientAliveInterval
Sets a timeout interval in seconds after which if no data has
been received from the client, sshd(8) will send a message
through the encrypted channel to request a response from the
client. The default is 0, indicating that these messages will
not be sent to the client. This option applies to protocol
version 2 only.
To update your server (and restart your sshd
)
echo "ClientAliveInterval 60" | sudo tee -a /etc/ssh/sshd_config
Or client-side:
echo "ServerAliveInterval 60" >> ~/.ssh/config
answered Sep 14, 2010 at 9:56
5
If you want to have a longer connection period, in the client add:
echo 'ServerAliveInterval 30' | tee -a ~/.ssh/config
echo 'ServerAliveCountMax 1200' | tee -a ~/.ssh/config
ServerAliveCountMax
by default this is set to 3. Therefore once the ServerAliveInterval
has sent 3 small packs of info to your server it will then automatically log out. Setting it to 1200 means this process will have to occur at least 1200 times. In short you should be connected at least 30*1200 seconds (10 hours).
answered Jul 4, 2015 at 22:40
4
An alternative solution would be to use mosh
— the mobile shell. In contrast to ssh it connects via UDP and supports roaming. You can start your session at home, suspend your laptop, take it to work / friends / wherever else you have internet, unsuspend your laptop and continue to work as if nothing has happened. It is especially useful if you are on a lousy internet connection: It shows instant feedback if your keystrokes don’t reach the server and continuously tries to reestablish the connection.
Installation and setup are simple: It is now included in all current Linux (plus a few non-Linux) distributions and it coordinates the session initialization and authentication via a prior ssh connection. So if you are able to connect via ssh user@server
you are very likely to be able to connect with mosh just by calling mosh user@server
, if the mosh packages are installed on both ends.
The main reason for connection failures is that you have to reach the server on a UDP port (default range: 60000-61000) for mosh to work. So if the server is behind a firewall you are mostly out of luck if can’t punch holes in it yourself (security implications).
answered Aug 11, 2014 at 8:26
PerseidsPerseids
4535 silver badges10 bronze badges
It usually means that your network (TCP) connection was reset. E.g. your internet provider reconnected you or something like this.
answered Sep 14, 2010 at 9:44
maxschlepzigmaxschlepzig
54.7k48 gold badges199 silver badges269 bronze badges
0
I spent lots of time messing with ServerAliveInterval and ClientAliveInterval variables with no joy.
Finally, after comparing with a machine that did not have the broken pipe problem, I found the directive at the bottom of /etc/ssh/sshd_config
:
KeepAlive yes
Putting this at the bottom of my problem server’s /etc/ssh/sshd_config
did the trick.
Verified for Ubuntu 20.04.1 LTS, Ubuntu 16.04.7 LTS.
answered Jan 6, 2021 at 23:38
3
Another cause for the «Broken Pipe message» is that another machine is attempting use the same IP as your host.
A simple way to test if someone else is using that IP:
- Turn off your host
- ping the same IP to see if another machine is using that IP
To find out which machines are on your network, you can use this Unix & Linux question title: How to find what other machines are connected to the local network.
answered Apr 26, 2013 at 21:06
JosirJosir
1303 bronze badges
1
I had the same problem but it is not as expected. If you find that on the same network another server is trying for the same IP address, you will face the same problem.
To solve this you need to check if there are other servers which use your same IP address. This can be done using the arp
command.
I am using Debian so here is a sample of the commands that I use to determine if another server was indeed using the same IP address
apt-get install arp-scan
arp-scan -I eth0 -l | grep 192.168.1.42
192.168.1.42 d4:eb:9a:f2:11:a1 (Unknown)
192.168.1.42 f4:23:a4:38:b5:76 (Unknown) (DUP: 2)
You will notice two sets of mac address using the same IP address. Avoid conflict by setting one to another IP address.
steve
21.1k4 gold badges46 silver badges74 bronze badges
answered Dec 29, 2015 at 8:56
You can use SSH/SCP argument ‘-o
‘ to accomplish that, no need to set your (if you’re admin) server’s ssh-config.
SSH options related to keeping connection alive are
TCPKeepAlive
,ServerAliveCountMax
,ServerAliveInterval
.
Basically, it goes like this:
% ssh -o TCPKeepAlive=yes
-o ServerAliveCountMax=20
-o ServerAliveInterval=15
user@server.example
, to have the client sending «keep-alive» messages every 15 seconds until the limit of 20 messages — which amounts to 20 x 15 seconds = 5 minutes
—, at which point the connection is considered broken/dead. The client process ends.
The man pages will give you more, detailed information:
- https://linux.die.net/man/5/ssh_config
answered Jul 23, 2020 at 8:56
BrandtBrandt
2721 gold badge2 silver badges10 bronze badges
For me this was because I had used ChrootDirectory
which requires that the entire path given be owned by root (which it was not for me). Changing the permissions for the path and restarting sshd fixed the problem.
answered Feb 2, 2021 at 11:58
QwertieQwertie
1,1643 gold badges13 silver badges27 bronze badges
2
Seeing «Broken pipe» in this situation is rare, but normal.
When you run type rvm | head -1
, bash executes type rvm
in one process, head -1
in another.1 The stdout of type
is connected to the «write» end of a pipe, the stdin of head
to the «read» end. Both processes run at the same time.
The head -1
process reads data from stdin (usually in chunks of 8 kB), prints out a single line (according to the -1
option), and exits, causing the «read» end of the pipe to be closed. Since the rvm
function is quite long (around 11 kB after being parsed and reconstructed by bash), this means that head
exits while type
still has a few kB of data to write out.
At this point, since type
is trying to write to a pipe whose other end has been closed – a broken pipe – the write() function it caled will return an EPIPE error, translated as «Broken pipe». In addition to this error, the kernel also sends the SIGPIPE signal to type
, which by default kills the process immediately.
(The signal is very useful in interactive shells, since most users do not want the first process to keep running and trying to write to nowhere. Meanwhile, non-interactive services ignore SIGPIPE – it would not be good for a long-running daemon to die on such a simple error – so they find the error code very useful.)
However, signal delivery is not 100% immediate, and there may be cases where write() returns EPIPE and the process continues to run for a short while before receiving the signal. In this case, type
gets enough time to notice the failed write, translate the error code and even print an error message to stderr before being killed by SIGPIPE. (The error message says «-bash: type:» since type
is a built-in command of bash itself.)
This seems to be more common on multi-CPU systems, since the type
process and the kernel’s signal delivery code can run on different cores, literally at the same time.
It would be possible to remove this message by patching the type
builtin (in bash’s source code) to immediately exit when it receives an EPIPE from the write() function.
However, it’s nothing to be concerned about, and it is not related to your rvm
installation in any way.
What can I do to configure SSH on both client and servers to prevent Write Failed: broken pipe
errors? It often occurs if you sleep your client computer and resume later.
LiveWireBT
28.2k25 gold badges107 silver badges217 bronze badges
asked Apr 28, 2012 at 23:36
11
I have tried this in /etc/ssh/ssh_config
for Linux and Mac:
Host *
ServerAliveInterval 120
This is how often, in seconds, it should send a keepalive message to the server. If that doesn’t work then train a monkey to press enter every two minutes while you work.
You could set either ServerAliveInterval
in /etc/ssh/ssh_config
of the client machine or ClientAliveInterval
in /etc/ssh/sshd_config
of the server machine. Try reducing the interval if you are still getting the error.
Configuration for a single user can be set in file ~/.ssh/config
both on the server and client side. Make sure the file has correct permissions chmod 644 ~/.ssh/config
.
answered May 26, 2012 at 11:49
Aram KocharyanAram Kocharyan
3,6502 gold badges14 silver badges8 bronze badges
19
SSH sessions may break due to numerous and possibly unavoidable reasons.
A useful utility which can be used to mitigate problems caused by this is called screen
. Screen is a powerful utility that allows you to control multiple terminals which will stay alive independently of the ssh session. For example, if you run screen
in an ssh session you will see a new terminal open and you can use that to run jobs. Lets say your ssh session dies in the process. Running screen -d
then screen -r
will reopen the last session and you will be able to continue from there. Make sure you read some of the documentation before using it.
answered Oct 4, 2012 at 16:28
eltommoeltommo
1,8941 gold badge12 silver badges11 bronze badges
9
Client configuration
Try creating the file:
~/.ssh/config
Add the contents:
Host *
ServerAliveInterval 30
ServerAliveCountMax 5
Now ssh to your server and see if your problem is fixed. ClientAliveInterval option is only useful when configuring the ssh server (aka sshd), it does not change a thing on the ssh client side, so don’t use it in the above configuration file.
This will send a hello-are-you-there signal to the server if no packets have been received in the preceding 30 seconds (as specified above). However, if the number of consecutive hello-are-you-there signals reach ServerAliveCountMax then ssh will disconnect from the server. This value is defaulting to 3 (so 3*30 = 90 seconds without server activity), increase it if it suits your needs. There are alot more config options to the .ssh/config file and you could read:
Using an SSH Config File
For more information on other options. You may not want to apply this to every server you connect to which this example will. Or restrain it to only a particular server by replacing the line Host *
with Host <IP>
(replace by an IP address, see ssh_config man page).
Server configuration
Similarly you can tell the server to be gentle with your clients. The configuration file is /etc/ssh/sshd_config
.
ClientAliveInterval 20
ClientAliveCountMax 5
You can either deactivate it by setting ClientAliveInterval
to 0
or tweak ClientAliveInterval
and ClientAliveCountMax
to set a maximum ssh client inactivity without responding to the probes. One advantage of this settings over TCPKeepAlive is that the signals are sent through the encrypted channels, so it is less likely to be spoofable.
answered Oct 6, 2013 at 2:54
MattMatt
6925 silver badges4 bronze badges
9
I’m remotely upgrading an Ubuntu server from lucid to precise and lost the ssh connection in the middle of the upgrade with the message «Write failed. Broken pipe». ClientAliveInterval and ServerAliveInterval did nothing. The solution is to turn on TCPKeepAlive options in client ssh:
TCPKeepAlive yes
in
/etc/ssh/ssh_config
Hope this will help
answered Oct 7, 2012 at 18:40
For the client, edit your ~/.ssh/config
(or /etc/ssh/ssh_config
) file as follow:
Host *
TCPKeepAlive yes
ServerAliveInterval 120
TCPKeepAlive — Specifies whether the system should send TCP keepalive
messages to the other side. If they are sent, death of the connection
or crash of one of the machines will be properly noticed. However,
this means that connections will die if the route is down temporarily,
and some people find it annoying (The default is ‘yes’).ServerAliveInterval — Sets a timeout interval in seconds after which
if no data has been received from the server, ssh(1) will send a
message through the encrypted channel to request a response from the
server. The default is 0, indicating that these messages will not be
sent to the server.
For the server, edit your /etc/ssh/sshd_config
as:
ClientAliveInterval 600
ClientAliveCountMax 0
If you want ssh client to exit (timeout) automatically after 10 minutes (600 seconds).
ClientAliveCountMax – This indicates the total number of checkalive
message sent by the ssh server without getting any response from the
ssh client. Default is 3.ClientAliveInterval – This indicates the timeout in seconds. After x
number of seconds, ssh server will send a message to the client asking
for response. Deafult is 0 (server will not send message to client to
check.).
See also: What do the options ServerAliveInterval
and ClientAliveInterval
in sshd_config do, precisely?
answered Oct 2, 2014 at 13:52
kenorbkenorb
9,6162 gold badges74 silver badges88 bronze badges
1
I absolutely love Mosh. I frequently ssh into a server, close my laptop and go to a cafe, open it up and carry on as if nothing changed.
Mosh (mobile shell)
Remote terminal application that allows roaming, supports intermittent
connectivity, and provides intelligent local
echo and line editing of user keystrokes.Mosh is a replacement for SSH. It’s more robust and responsive,
especially over Wi-Fi, cellular, and long-distance links.Mosh is free software, available for GNU/Linux, FreeBSD, Solaris, Mac OS X, and Android.
answered Sep 30, 2014 at 18:48
JakeJake
3012 silver badges3 bronze badges
For me, I was getting Write failed: Broken pipe
even when I was actively typing in vim or at the shell prompt. I couldn’t browse the internet locally either for awhile either. (I was connecting remotely to Ubuntu using Terminal.)
Others in my network stream a lot of video from Netflix and other places. I can’t prove it, but I suspect its an ISP or router issue. For example, Verizon and Netflix are pointing fingers at each other for their customer’s network problems.
If you’ve got a dial-up connection and are streaming video or music with a simultaneous SSH or telnet connection, it’s inevitable at some point you’ll get a broken pipe message. Upgrading my ISPs broadband package seemed to make my broken connection less frequent.
answered Jul 30, 2014 at 13:33
pmaguniapmagunia
1,3321 gold badge10 silver badges14 bronze badges
answered Jan 25, 2019 at 3:13
rupert160rupert160
1711 silver badge2 bronze badges
I have a script on the remote server that never seems to fails, regardless of the SSH configuration client or server.
#!/bin/bash
while true; do date; sleep 10; done;
Save it to some dummy.sh file and quickly run it before you minimize the window or move away from it. It will keep printing the current time stamp on the server and keeps your connection alive as long as the connection is not dropped by any other reason. When you get back to that terminal, just hit CTRL+C and keep working.
answered Sep 9, 2013 at 16:50
JulioHMJulioHM
6341 gold badge5 silver badges11 bronze badges
2
You can add these args every time you invoke ssh: -o ServerAliveInterval=15 -o ServerAliveCountMax=3
You don’t have to edit /etc/ssh/*config files if you do this.
You can create an bash alias or function or script to make this easy.
E.g. these bash functions, you can add into your .bashrc, do_ssh is used manually to turn on keepalives. do_ssh_pty is used within scripts to set pty and avoid prompts.
do_ssh() {
ssh -o ServerAliveInterval=15 -o ServerAliveCountMax=3 $*
}
do_ssh_pty() {
ssh -tt -o "BatchMode=yes" -o "StrictHostKeyChecking=no" -o ServerAliveInterval=15 -o ServerAliveCountMax=3 $*
}
Now do_ssh user@host
can be used or do_ssh user@host <args> <command>
and keepalives will be active.
answered Feb 12, 2018 at 13:05
gaoithegaoithe
5134 silver badges10 bronze badges
1
Table of Contents
1
Introduction
While trying to SSH we may get this error “client_loop: send disconnect: Broken pipe”. The reason behind the cause is, a normal user added with a SELinux user should be allowed to do SSH by enabling 1 for ssh_sysadm_login
Checking logs
Let’s check the logs, we could get something.
# journalctl -f
Aug 09 11:09:52 server1.linuxsysadmins.local sshd[3321]: fatal: sshd_selinux_copy_context: setcon failed with Permission denied
We get to know it’s a Permission denied error for some reason.
Check for AVC
Check the audit logs for any AVC.
# ausearch -i -m avc
node=server1.linuxsysadmins.local type=AVC msg=audit(08/09/2022 11:09:52.762:2571) : avc: denied { dyntransition } for pid=3321 comm=sshd scontext=system_u:system_r:sshd_t:s0-s0:c0.c1023 tcontext=sysadm_u:sysadm_r:sysadm_t:s0-s0:c0.c1023 tclass=process permissive=0
Finding Solutions
If found any AVC, then find the cause why its getting denied with the help of audit2allow.
# audit2allow -w -a
-w | --why
Translates SELinux audit messages into a description of why the access was denied. -a | --all
Read input from audit and message log, conflicts with -i
Solution
Set the ssh_sysadm_login SELinux boolean to 1.
# setsebool -P ssh_sysadm_login on
Verify the changes.
# getsebool -a | grep ssh
You may need to know more about SELinux Confining Users
Conclusion
As part of System Hardening we may need to configure specific users as per the requirement. Failing to configure SELinux for a normal user can throw permission denied.
Вас тоже бесит постоянно отваливающееся соединение SSH? Меня это пипец как бесит. Особенно когда пишешь длинную команду, нажимаешь Enter, а тебе вываливается «client_loop: send disconnect: Broken pipe». И снова подключаешься.
Поиск по интернетам ничего не давал кроме того, что тут и там советовали раскомментировать директиву ClientAliveInterval, причем советовали установить значение в 300, причем не объясняя почему именно 300 и что вообще такое ClientAliveInterval.
Само собой я последовал совету и поставил ClientAliveInterval равным 300. Соединение как разрывалось до этого, так и дальше продолжало разрываться. А потом я где-то нашел совет добавить директиву ServerAliveInterval. В итоге сервер перестал отвечать и пришлось восстанавливать бэкап. Тем самым в трубу улетели кучи и кучи настроек, поскольку бэкап был один единственный и там была система в дефолтном состоянии.
За что отвечает директива ClientAliveInterval?
Значение этой директивы определяет через какой промежуток времени начиная с момента простоя клиенту будет отправлен запрос отклика. По умолчанию ClientAliveInterval равен 0, то есть сервер не будет ничего делать.
Простыми словами. У вас открыт терминал, вы подключены к серверу. Выполнили пару команд и ушли читать мануал. Допустим ClientAliveInterval у нас 30, это значи через 30 секунд после последней нашей активности, сервер проверит подключены ли мы к серверу, получив отклик от клиента, сервер не будет разрывать соединение.
Ну вроде как все понятно. Но! Чисто гипотетически мы можем быть подключены не через самое надежное соединение. Например через USB-модем в зоне со слабым сигналом. Предположим в какой-то момент сигнал упал, а сервер нам шлет запрос. Клиент его не получит. Тут на сцену выходит другая директива.
Директива ClientAliveCountMax
По умолчанию значение ClientAliveCountMax равно 3. То есть получается что сервер отправит нам максимум три запроса без подтверждения и уже только тогда закроет соединение.
Если ClientAliveInterval равен 30, а ClientAliveCountMax 3, то сервер закроет соединение через 90 секунд, то есть через полторы минуты, если наш модем за это время не восстановит соединение.
Как видите мы гибко можем манипулировать настройками этих двух директив в зависимости от обстоятельств.
Директива TCPKeepAlive
По умолчанию эта директива имеет значение yes. При активации ClientAliveInterval директиву TCPKeepAlive имеет смысл перевести в no. По сути сама по себе директива ничем особенным не помогает и не мешает, просто по мнению спецов, она может помочь злоумышленникам в атаке на сервер.
Добавляем настройки
Обращаю внимание: настройки происходят на сервере, а не на клиенте.
У меня в Ubuntu Server 20.04 в файле /etc/ssh/sshd_config присутствует
Include /etc/ssh/sshd_config.d/*.conf
Поэтому я просто создаю новый файл
sudo nano /etc/ssh/sshd_config.d/alive.conf
И уже туда втыкаем
ClientAliveInterval 30
ClientAliveCountMax 30
TCPKeepAlive no
Я думаю этих настроек боле чем достаточно чтобы соединение долго не отваливалось в течении 15 минут. Это может показаться чрезмерным, но бывает всякое.
Если вы используете SSH для подключения к удаленным серверам Linux, вы заметите, что если вы оставите сеанс SSH неактивным в течение некоторого времени, а затем попытаетесь использовать его снова, сеанс SSH отключается с сообщением об ошибке, например:
:client_loop: send disconnect: Broken pipe
В некоторых системах отображается сообщение: ‘Write failed: Broken pipe’ or ‘Connection closed by remote host’.
Давайте посмотрим, что вызывает эту ошибку и как сохранить соединение SSH.
Исправление ошибки сломанной трубы с помощью SSH
Как вы уже догадались, соединение SSH закрыто из-за бездействия. Нет установленного значения, но обычно оно составляет около 5 минут или около того.
Что вы можете сделать, чтобы избежать отключения сеанса SSH, — это отправить «живое сообщение» либо с сервера клиенту ( ClientAliveInterval), либо от клиента к серверу ( ServerAliveInterval) через определенный интервал времени.
Таким образом, вы поддерживаете сеанс SSH в активном состоянии, потому что между клиентом и сервером существует связь, и сервер понимает, что клиент все еще существует.
Есть два способа сделать это. Либо вы отправляете живое сообщение от клиента к серверу, либо с сервера клиенту.
- Если вы подключаетесь к нескольким серверам через SSH, установите его на своем компьютере.
- Если вы системный администратор и несколько пользователей жалуются на частое отключение SSH-соединения, вы можете установить его на сервере.
Метод 1: изменение конфигурации SSH на стороне клиента
Предположим, вы хотите, чтобы ваше SSH-соединение оставалось активным до 10 минут (600 секунд) простоя.
При подключении к удаленной системе Linux через SSH вы можете указать значение ServerAliveInterval:
ssh -o ServerAliveInterval=600 username@server_ip_address
Теперь это работает, но вручную вводить эту опцию каждый раз, когда вы подключаетесь к серверу, утомительно. Почему бы не сделать его постоянным?
Надеюсь, вы знаете о файлах конфигурации SSH. На стороне клиента вы можете воспользоваться этим, чтобы установить определенные параметры SSH для определенных подключений или всех из них.
Во-первых, убедитесь, что у вас есть файл конфигурации ssh. Если не создать:
touch ~/.ssh/config
Важно предоставить ему правильные права доступа к файлам, в противном случае при подключении через SSH у вас будет ошибка отказа в разрешении.
Используйте команду chmod и добавьте к ней следующие права доступа к файлу:
chmod 600 ~/.ssh/config
Если вам лень или вы не хотите вдаваться в подробности, используйте эту команду, чтобы установить интервал активности на 600 секунд (10 минут):
echo "ServerAliveInterval 600" >> ~/.ssh/config
Это установит значение ServerAliveInterval на 10 минут для всех SSH-соединений, которые вы будете использовать. Попробуйте, если хотите.
Если вы хотите сделать его более правильным, вы должны добавить его так:
Host * ServerAliveInterval 600
Метод 2: изменение конфигурации SSH на стороне сервера
Файл конфигурации SSH для сервера обычно находится в /etc/ssh/sshd_config.
Если вы откроете этот файл, вы найдете здесь два интересующих параметра:
- ClientAliveInterval: Это период времени бездействия, по истечении которого сервер отправит сообщение об активности подключенному по ssh клиенту.
- ClientAliveCountMax: Это количество попыток, которые сервер сделает для отправки живого сообщения.
Скажем, вы установили ClientAliveInterval в 200 секунд и ClientAliveCountMax в 3. Это означает, что сервер отправит живое сообщение через 200 секунд. Если со стороны клиента нет активности, он снова отправит живое сообщение через 400 секунд. Нет ответа/активности от клиента, и другое живое сообщение отправлено через 600 секунд. По истечении этого времени (600 секунд) соединение SSH прерывается.
Вы можете отредактировать файл /etc/ssh/sshd_config в своем любимом текстовом редакторе на базе терминала, таком как Vim. Найдите записи ClientAliveInterval и ClientAliveCountMax. Удалите ключ # в начале строк и присвойте им соответствующее значение.
Сохраните и выйдите из файла.
Пожалуйста, не устанавливайте тайм-аут SSH-соединения на несколько часов. Это было бы пустой тратой ресурсов.
Мы надеемся, что эта статья помогла вам решить проблему с ошибкой сломанной трубы при SSH-соединении. Ваше мнение приветствуется.
Если вы нашли ошибку, пожалуйста, выделите фрагмент текста и нажмите Ctrl+Enter.
A pipe connects two processes. One of these processes holds the read-end of the pipe, and the other holds the write-end.
When the pipe is written to, data is stored in a buffer waiting for the other processes to retrieve it.
What happens if a process is writing to a pipe, but the process on the other side suddenly exits or closes the pipe? Or the other way round, a process is reading just as the writer finishes or closes?
This input/output error is called a broken pipe.