Создание сетевых пространств (network namespaces):
sudo ip netns add Client
sudo ip netns add Server
Создание виртуальных интерфейсов (veth):
Теперь у тебя есть связанная пара интерфейсов (veth-client <-> veth-server).
sudo ip link add veth-client type veth peer name veth-server
Привязка интерфейсов к namespace:
sudo ip link set veth-client netns Client
sudo ip link set veth-server netns Server
Настройка IP-адресов:
sudo ip netns exec Client ip addr add 192.168.1.1/24 dev veth-client
sudo ip netns exec Server ip addr add 192.168.1.2/24 dev veth-server
Теперь у тебя есть два "виртуальных хоста" (Client и Server), соединенных через veth.
В Client и Server прописываешь маршруты:
sudo ip netns exec Client ip route add default via 192.168.1.254
sudo ip netns exec Server ip route add default via 192.168.2.254
Список всех network namespaces:
sudo ip netns list
ls /var/run/netns/
Просмотр интерфейсов внутри конкретного netns:
sudo ip netns exec Client ip link show
sudo ip -n Client link
Просмотр IP-адресов внутри netns:
sudo ip netns exec Client ip addr
Просмотр таблицы маршрутизации в netns:
sudo ip netns exec Client ip route
sudo ip -n Client route
Проверить ARP-таблицу (соседей):
sudo ip netns exec Client ip neigh
Если netns нет в списке, но процесс использует его:
lsns -t net
ps aux | grep "netns"
Использование namespace:
ip netns exec bash
ip netns exec Client bash
ip netns exec Server bash
Пример скрипта который создаст пространства имен, привяжет интерфейсы к ним, добавит адреса, добавит маршруты:
#!/bin/bash
set -x
# Создание namespace'ов, если их ещё нет
ip netns add Server
ip netns add Client
echo "setup Server:"
ip link set enp1s0f0np0 down
ip link set enp1s0f0np0 netns Server
ip netns exec Server ip addr add 10.0.12.2/24 dev enp1s0f0np0
ip netns exec Server ip link set enp1s0f0np0 up
ip netns exec Server ip link set lo up
ip netns exec Server ip route add default via 10.0.12.1 dev enp1s0f0np0
echo "setup Client:"
ip link set enp1s0f1np1 down
ip link set enp1s0f1np1 netns Client
ip netns exec Client ip addr add 10.0.11.2/24 dev enp1s0f1np1
ip netns exec Client ip link set enp1s0f1np1 up
ip netns exec Client ip link set lo up
ip netns exec Client ip route add default via 10.0.11.1 dev enp1s0f1np1
# Удаление namespace'ов при необходимости
# ip netns delete Client
# ip netns delete Server
Использование namespace:
Команда:
ip netns exec bash
Пример:
ip netns exec Server bash
ip netns exec Client bash
xrdp будет работать с xfc4 удаленно
kde будем пользовать локально
Установка пакетов:
Консольные утилиты:
apt install vim tmux tcpdump curl mc minicom
Ставим пакеты для xrdp:
apt install xrdp xorgxrdp ssl-cert
Установка xfce4:
apt install xfce4 xfce4-goodies xfce4-places-plugin task-xfce-desktop
Установка kde:
apt install kde-full
Решение ошибки при подключении по rdp:
apt install dbus-x11
Решение проблемы зависания консоли:
apt-get remove xscreensaver
Дополнительные программы:
apt install desktop-telegram vscode golang gparted
Настройки:
0. Отключаем постоянные запросы паролей при настройке под учетной записью из группы admin
usermod -aG admin username
0.1 Политики polkit-1 такие полезные
vim /etc/polkit-1/localauthority/50-local.d/46-all-allow.pkla
-----------------------------------------------------------------------
[Allow ALL from group admin]
Identity=unix-group:admin
Action=*
ResultAny=yes
ResultInactive=yes
ResultActive=yes
-----------------------------------------------------------------------
0.2 или
!!! Вместо auth_admin_keep указываем yes
vim /usr/share/polkit-1/actions/org.freedesktop.login1.policy
-------------------------------------------------------------
Reboot the systemAuthentication is required for rebooting the system.yesyesyesorg.freedesktop.login1.set-wall-message
-------------------------------------------------------------
vim /usr/share/polkit-1/actions/org.freedesktop.NetworkManager.policy
---------------------------------------------------------------------
[...]
auth_admin_keepyesyes
---------------------------------------------------------------------
P.S Более правильно все таки решить все с помощью pkla
1. Переконфигурируем:
dpkg-reconfigure xserver-xorg-legacy - переключаем разрешение для всех
2. Редактируем выбор раскладки
vim /etc/xrdp/xrdp_keyboard.ini
---------------------------
[default_rdp_layouts] # ищем и убеждаемся что файлы существуют
rdp_layout_us=0x00000409 # ищем и убеждаемся что файлы существуют
rdp_layout_ru=0x00000419 # ищем и убеждаемся что файлы существуют
[layouts_map_ru]
rdp_layout_us=ru,us
rdp_layout_ru=ru,us
[rdp_keyboard_ru]
keyboard_type=4
keyboard_type=7
keyboard_subtype=1
; model=pc105 при необходимости
options=grp:alt_shift_toggle
rdp_layouts=default_rdp_layouts
layouts_map=layouts_map_ru
3. Добавить пользователя xrdp в группу ssl-cert
usermod -aG ssl-cert xrdp
4. Выпуск собственного сертификата для XRDP
mkdir /etc/xrdp/certificate/
cd /etc/xrdp/certificate/
openssl req -x509 -newkey rsa:2048 -nodes -keyout key.pem -out cert.pem -days 3650
4.1 Подключаем сертификаты отредактировав файл
!!! ищем строки (certificate=) и (key_file=) и правим их
vim /etc/xrdp/xrdp.ini
----------------------
certificate=/etc/xrdp/certificate/cert.pem
key_file=/etc/xrdp/certificate/key.pem
----------------------
4.2 Изменяем права для файла
chown -R xrdp:xrdp /etc/xrdp/certificate/
5. Запрет авторизации ROOT в XRDP
vim /etc/xrdp/sesman.ini
-------------------------
[Security]
# Авторизация root. true - разрешено false - запрещено
AllowRootLogin=false
-------------------------
6. XRDP черный экран при подключении:
!!! Баг был при использовании использовании ubuntu, debian 10, debian 11
!!! В окружение KDE
!!! Нужно вставить следующие строки в файл /etc/xrdp/startwm.sh
!!! unset DBUS_SESSION_BUS_ADDRESS
!!! unset XDG_RUNTIME_DIR
6.1 vim /etc/xrdp/startwm.sh
------------------------
#!/bin/sh
# xrdp X session start script (c) 2015, 2017 mirabilos
# published under The MirOS Licence
if test -r /etc/profile; then
. /etc/profile
fi
unset DBUS_SESSION_BUS_ADDRESS
unset XDG_RUNTIME_DIR
if test -r /etc/default/locale; then
. /etc/default/locale
test -z "${LANG+x}" || export LANG
test -z "${LANGUAGE+x}" || export LANGUAGE
test -z "${LC_ADDRESS+x}" || export LC_ADDRESS
test -z "${LC_ALL+x}" || export LC_ALL
test -z "${LC_COLLATE+x}" || export LC_COLLATE
test -z "${LC_CTYPE+x}" || export LC_CTYPE
test -z "${LC_IDENTIFICATION+x}" || export LC_IDENTIFICATION
test -z "${LC_MEASUREMENT+x}" || export LC_MEASUREMENT
test -z "${LC_MESSAGES+x}" || export LC_MESSAGES
test -z "${LC_MONETARY+x}" || export LC_MONETARY
test -z "${LC_NAME+x}" || export LC_NAME
test -z "${LC_NUMERIC+x}" || export LC_NUMERIC
test -z "${LC_PAPER+x}" || export LC_PAPER
test -z "${LC_TELEPHONE+x}" || export LC_TELEPHONE
test -z "${LC_TIME+x}" || export LC_TIME
test -z "${LOCPATH+x}" || export LOCPATH
fi
if test -r /etc/profile; then
. /etc/profile
fi
test -x /etc/X11/Xsession && exec /etc/X11/Xsession
exec /bin/sh /etc/X11/Xsession
------------------------
7. Название подключенной локальной папки в XRDP
!!! для корректной работы нужны пакеты
!!! apt install gvfs-fuse gvfs-backends libglib2.0-bin
vim /etc/xrdp/sesman.ini
------------------------
FuseMountName=Mount_FOLDER
------------------------
8. Настройка вида окна авторизации XRDP
vim /etc/xrdp/xrdp.ini
-----------------------
ls_title=YOU SUPER SERVER # заголовок окна сервера
ls_top_window_bg_color=000000 # Цвет фона RGB
ls_logo_filename=/etc/xrdp/logo_xrdp.bmp #Логотип
; Session types # После этой строки ищем и убираем лишние сессии, оставляем только [Xorg]
-----------------------
9. Отключение screensaver
Вариант первый, можно просто его удалить
apt-get remove xscreensaver
Вариант второй, можно настроить электропитание в настройках экрана
10. После настройки перезапустим xrdp
service xrdp restart
[Globals]
; xrdp.ini file version number
ini_version=1
; fork a new process for each incoming connection
fork=true
; ports to listen on, number alone means listen on all interfaces
; 0.0.0.0 or :: if ipv6 is configured
; space between multiple occurrences
; ALL specified interfaces must be UP when xrdp starts, otherwise xrdp will fail to start
;
; Examples:
; port=3389
; port=unix://./tmp/xrdp.socket
; port=tcp://.:3389 127.0.0.1:3389
; port=tcp://:3389 *:3389
; port=tcp://:3389 192.168.1.1:3389
; port=tcp6://.:3389 ::1:3389
; port=tcp6://:3389 *:3389
; port=tcp6://{}:3389 {FC00:0:0:0:0:0:0:1}:3389
; port=vsock://:
port=3389
; 'port' above should be connected to with vsock instead of tcp
; use this only with number alone in port above
; prefer use vsock://: above
use_vsock=false
; regulate if the listening socket use socket option tcp_nodelay
; no buffering will be performed in the TCP stack
tcp_nodelay=true
; regulate if the listening socket use socket option keepalive
; if the network connection disappear without close messages the connection will be closed
tcp_keepalive=true
; set tcp send/recv buffer (for experts)
#tcp_send_buffer_bytes=32768
#tcp_recv_buffer_bytes=32768
; security layer can be 'tls', 'rdp' or 'negotiate'
; for client compatible layer
security_layer=negotiate
; minimum security level allowed for client for classic RDP encryption
; use tls_ciphers to configure TLS encryption
; can be 'none', 'low', 'medium', 'high', 'fips'
crypt_level=high
; X.509 certificate and private key
; openssl req -x509 -newkey rsa:2048 -nodes -keyout key.pem -out cert.pem -days 365
; note this needs the user xrdp to be a member of the ssl-cert group, do with e.g.
;$ sudo adduser xrdp ssl-cert
;certificate=
;key_file=
certificate=/etc/xrdp/certificate/cert.pem
key_file=/etc/xrdp/certificate/key.pem
; set SSL protocols
; can be comma separated list of 'SSLv3', 'TLSv1', 'TLSv1.1', 'TLSv1.2', 'TLSv1.3'
ssl_protocols=TLSv1.2, TLSv1.3
; set TLS cipher suites
#tls_ciphers=HIGH
; concats the domain name to the user if set for authentication with the separator
; for example when the server is multi homed with SSSd
#domain_user_separator=@
; The following options will override the keyboard layout settings.
; These options are for DEBUG and are not recommended for regular use.
#xrdp.override_keyboard_type=0x04
#xrdp.override_keyboard_subtype=0x01
#xrdp.override_keylayout=0x00000409
; Section name to use for automatic login if the client sends username
; and password. If empty, the domain name sent by the client is used.
; If empty and no domain name is given, the first suitable section in
; this file will be used.
autorun=
allow_channels=true
allow_multimon=true
bitmap_cache=true
bitmap_compression=true
bulk_compression=true
#hidelogwindow=true
max_bpp=32
new_cursors=true
; fastpath - can be 'input', 'output', 'both', 'none'
use_fastpath=both
; when true, userid/password *must* be passed on cmd line
#require_credentials=true
; when true, the userid will be used to try to authenticate
#enable_token_login=true
; You can set the PAM error text in a gateway setup (MAX 256 chars)
#pamerrortxt=change your password according to policy at http://url
;
; colors used by windows in RGB format
;
blue=009cb5
grey=dedede
#black=000000
#dark_grey=808080
#blue=08246b
#dark_blue=08246b
#white=ffffff
#red=ff0000
#green=00ff00
#background=626c72
;
; configure login screen
;
; Login Screen Window Title
#ls_title=My Login Title
; top level window background color in RGB format
ls_top_window_bg_color=009cb5
; width and height of login screen
;
; The default height allows for about 5 fields to be comfortably displayed
; above the buttons at the bottom. To display more fields, make
; larger, and also increase and
; below
;
ls_width=350
ls_height=430
; login screen background color in RGB format
ls_bg_color=dedede
; optional background image filename. BMP format is always supported,
; but other formats will be supported if xrdp is build with imlib2
; The transform can be one of the following:-
; none : No transformation. Image is placed in bottom-right corner
; of the screen.
; scale : Image is scaled to the screen size. The image aspect
; ratio is not preserved.
; zoom : Image is scaled to the screen size. The image aspect
; ratio is preserved by clipping the image.
#ls_background_image=
#ls_background_transform=none
; logo
; full path to file or file in shared folder. BMP format is always supported,
; but other formats will be supported if xrdp is build with imlib2
; For transform values, see 'ls_background_transform'. The logo width and
; logo height are ignored for a transform of 'none'.
ls_logo_filename=
#ls_logo_transform=none
#ls_logo_width=240
#ls_logo_height=140
ls_logo_x_pos=55
ls_logo_y_pos=50
; for positioning labels such as username, password etc
ls_label_x_pos=30
ls_label_width=65
; for positioning text and combo boxes next to above labels
ls_input_x_pos=110
ls_input_width=210
; y pos for first label and combo box
ls_input_y_pos=220
; OK button
ls_btn_ok_x_pos=142
ls_btn_ok_y_pos=370
ls_btn_ok_width=85
ls_btn_ok_height=30
; Cancel button
ls_btn_cancel_x_pos=237
ls_btn_cancel_y_pos=370
ls_btn_cancel_width=85
ls_btn_cancel_height=30
[Logging]
; Note: Log levels can be any of: core, error, warning, info, debug, or trace
LogFile=xrdp.log
LogLevel=INFO
EnableSyslog=true
#SyslogLevel=INFO
#EnableConsole=false
#ConsoleLevel=INFO
#EnableProcessId=false
[LoggingPerLogger]
; Note: per logger configuration is only used if xrdp is built with
; --enable-devel-logging
#xrdp.c=INFO
#main()=INFO
[Channels]
; Channel names not listed here will be blocked by XRDP.
; You can block any channel by setting its value to false.
; IMPORTANT! All channels are not supported in all use
; cases even if you set all values to true.
; You can override these settings on each session type
; These settings are only used if allow_channels=true
rdpdr=true
rdpsnd=true
drdynvc=true
cliprdr=true
rail=true
xrdpvr=true
tcutils=true
driveredir=true
; for debugging xrdp, in section xrdp1, change port=-1 to this:
#port=/tmp/.xrdp/xrdp_display_10
;
; Session types
;
; Some session types such as Xorg, X11rdp and Xvnc start a display server.
; Startup command-line parameters for the display server are configured
; in sesman.ini. See and configure also sesman.ini.
[Xorg]
name=Xorg
lib=libxup.so
username=ask
password=ask
ip=127.0.0.1
port=-1
code=20
;[Xvnc]
;name=Xvnc
;lib=libvnc.so
;username=ask
;password=ask
;ip=127.0.0.1
;port=-1
#xserverbpp=24
#delay_ms=2000
; Disable requested encodings to support buggy VNC servers
; (1 = ExtendedDesktopSize)
#disabled_encodings_mask=0
; Use this to connect to a chansrv instance created outside of sesman
; (e.g. as part of an x11vnc console session). Replace '0' with the
; display number of the session
#chansrvport=DISPLAY(0)
; Generic VNC Proxy
; Tailor this to specific hosts and VNC instances by specifying an ip
; and port and setting a suitable name.
;[vnc-any]
;name=vnc-any
;lib=libvnc.so
;ip=ask
;port=ask5900
;username=na
;password=ask
#pamusername=asksame
#pampassword=asksame
#pamsessionmng=127.0.0.1
#delay_ms=2000
; Generic RDP proxy using NeutrinoRDP
; Tailor this to specific hosts by specifying an ip and port and setting
; a suitable name.
;[neutrinordp-any]
;name=neutrinordp-any
; To use this section, you should build xrdp with configure option
; --enable-neutrinordp.
;lib=libxrdpneutrinordp.so
;ip=ask
;port=ask3389
;username=ask
;password=ask
; Uncomment the following lines to enable PAM authentication for proxy
; connections.
#pamusername=ask
#pampassword=ask
#pamsessionmng=127.0.0.1
; Currently NeutrinoRDP doesn't support dynamic resizing. Uncomment
; this line if you're using a client which does.
#enable_dynamic_resizing=false
; By default, performance settings requested by the RDP client are ignored
; and chosen by NeutrinoRDP. Uncomment this line to allow the user to
; select performance settings in the RDP client.
#perf.allow_client_experiencesettings=true
; Override any experience setting by uncommenting one or more of the
; following lines.
#perf.wallpaper=false
#perf.font_smoothing=false
#perf.desktop_composition=false
#perf.full_window_drag=false
#perf.menu_anims=false
#perf.themes=false
#perf.cursor_blink=false
; By default NeutrinoRDP supports cursor shadows. If this is giving
; you problems (e.g. cursor is a black rectangle) try disabling cursor
; shadows by uncommenting the following line.
#perf.cursor_shadow=false
; By default, NeutrinoRDP uses the keyboard layout of the remote RDP Server.
; If you want to tell the remote the keyboard layout of the RDP Client,
; by uncommenting the following line.
#neutrinordp.allow_client_keyboardLayout=true
; The following options will override the remote keyboard layout settings.
; These options are for DEBUG and are not recommended for regular use.
#neutrinordp.override_keyboardLayout_mask=0x0000FFFF
#neutrinordp.override_kbd_type=0x04
#neutrinordp.override_kbd_subtype=0x01
#neutrinordp.override_kbd_fn_keys=12
#neutrinordp.override_kbd_layout=0x00000409
; You can override the common channel settings for each session type
#channel.rdpdr=true
#channel.rdpsnd=true
#channel.drdynvc=true
#channel.cliprdr=true
#channel.rail=true
#channel.xrdpvr=true
config /etc/xrdp/sesman.ini
;; See `man 5 sesman.ini` for details
[Globals]
ListenAddress=127.0.0.1
ListenPort=3350
EnableUserWindowManager=true
; Give in relative path to user's home directory
UserWindowManager=startwm.sh
; Give in full path or relative path to /etc/xrdp
DefaultWindowManager=startwm.sh
; Give in full path or relative path to /etc/xrdp
ReconnectScript=reconnectwm.sh
[Security]
;AllowRootLogin=true
AllowRootLogin=false
MaxLoginRetry=4
TerminalServerUsers=tsusers
TerminalServerAdmins=tsadmins
; When AlwaysGroupCheck=false access will be permitted
; if the group TerminalServerUsers is not defined.
AlwaysGroupCheck=false
; When RestrictOutboundClipboard=all clipboard from the
; server is not pushed to the client.
; In addition, you can control text/file/image transfer restrictions
; respectively. It also accepts comma separated list such as text,file,image.
; To keep compatibility, some aliases are also available:
; true: an alias of all
; false: an alias of none
; yes: an alias of all
RestrictOutboundClipboard=none
; When RestrictInboundClipboard=all clipboard from the
; client is not pushed to the server.
; In addition, you can control text/file/image transfer restrictions
; respectively. It also accepts comma separated list such as text,file,image.
; To keep compatibility, some aliases are also available:
; true: an alias of all
; false: an alias of none
; yes: an alias of all
RestrictInboundClipboard=none
[Sessions]
;; X11DisplayOffset - x11 display number offset
; Type: integer
; Default: 10
X11DisplayOffset=10
;; MaxSessions - maximum number of connections to an xrdp server
; Type: integer
; Default: 0
MaxSessions=50
;; KillDisconnected - kill disconnected sessions
; Type: boolean
; Default: false
; if 1, true, or yes, every session will be killed within DisconnectedTimeLimit
; seconds after the user disconnects
KillDisconnected=false
;; DisconnectedTimeLimit (seconds) - wait before kill disconnected sessions
; Type: integer
; Default: 0
; if KillDisconnected is set to false, this value is ignored
DisconnectedTimeLimit=0
;; IdleTimeLimit (seconds) - wait before disconnect idle sessions
; Type: integer
; Default: 0
; Set to 0 to disable idle disconnection.
IdleTimeLimit=0
;; Policy - session allocation policy
; Type: enum [ "Default" | "UBD" | "UBI" | "UBC" | "UBDI" | "UBDC" ]
; "Default" session per
; "UBD" session per
; "UBI" session per
; "UBC" session per
; "UBDI" session per
; "UBDC" session per
Policy=Default
[Logging]
; Note: Log levels can be any of: core, error, warning, info, debug, or trace
LogFile=xrdp-sesman.log
LogLevel=INFO
EnableSyslog=true
#SyslogLevel=INFO
#EnableConsole=false
#ConsoleLevel=INFO
#EnableProcessId=false
[LoggingPerLogger]
; Note: per logger configuration is only used if xrdp is built with
; --enable-devel-logging
#sesman.c=INFO
#main()=INFO
;
; Session definitions - startup command-line parameters for each session type
;
[Xorg]
; Specify the path of non-suid Xorg executable. It might differ depending
; on your distribution and version. Find out the appropriate path for your
; environment. The typical path is known as follows:
;
; Fedora 26 or later : param=/usr/libexec/Xorg
; Debian 9 or later : param=/usr/lib/xorg/Xorg
; Ubuntu 16.04 or later : param=/usr/lib/xorg/Xorg
; Arch Linux : param=/usr/lib/Xorg
; CentOS 7 : param=/usr/bin/Xorg or param=Xorg
; CentOS 8 : param=/usr/libexec/Xorg
; FreeBSD (from 2022Q4) : param=/usr/local/libexec/Xorg
;
param=/usr/lib/xorg/Xorg
; Leave the rest parameters as-is unless you understand what will happen.
param=-config
param=xrdp/xorg.conf
param=-noreset
param=-nolisten
param=tcp
param=-logfile
param=.xorgxrdp.%s.log
[Xvnc]
param=Xvnc
param=-bs
param=-nolisten
param=tcp
param=-localhost
param=-dpi
param=96
[Chansrv]
; drive redirection
; See sesman.ini(5) for the format of this parameter
;FuseMountName=/run/user/%u/thinclient_drives
;FuseMountName=/media/thinclient_drives/%U/thinclient_drives
FuseMountName=remoute
; this value allows only the user to access their own mapped drives.
; Make this more permissive (e.g. 022) if required.
;FileUmask=077
; Can be used to disable FUSE functionality - see sesman.ini(5)
;EnableFuseMount=false
; Uncomment this line only if you are using GNOME 3 versions 3.29.92
; and up, and you wish to cut-paste files between Nautilus and Windows. Do
; not use this setting for GNOME 4, or other file managers
UseNautilus3FlistFormat=true
[ChansrvLogging]
; Note: one log file is created per display and the LogFile config value
; is ignored. The channel server log file names follow the naming convention:
; xrdp-chansrv.${DISPLAY}.log
;
; Note: Log levels can be any of: core, error, warning, info, debug, or trace
LogLevel=INFO
EnableSyslog=true
#SyslogLevel=INFO
#EnableConsole=false
#ConsoleLevel=INFO
#EnableProcessId=false
[ChansrvLoggingPerLogger]
; Note: per logger configuration is only used if xrdp is built with
; --enable-devel-logging
#chansrv.c=INFO
#main()=INFO
[SessionVariables]
PULSE_SCRIPT=/etc/xrdp/pulse/default.pa
xrdp белый экран raspberry pi
https://bbs.archlinux.org/viewtopic.php?id=277905
https://askubuntu.com/questions/1209300/remote-desktop-on-raspberrypi-not-working
https://raspberrypi.stackexchange.com/questions/133425/connection-problem-giving-up-on-xrdp-with-raspberry-pi-os-11-bullseye
https://github.com/neutrinolabs/xrdp/issues/2053 #Не очевидное решение проблемы белого экрана на raspberry
https://github.com/neutrinolabs/xrdp/wiki/Tips-and-FAQ#why-cant-i-log-the-same-user-on-on-the-graphical-console-and-over-xrdp-at-the-same-time
Вариант 0:
СМОТРИМ ЛОГИ!!!
cat /var/log/xrdp-sesman.log
В каталоге пользователя:
cat .xorgxrdp.*.log
cat .xsession
cat .xsession-errors
Смотрим при подключении:
journalctl -f
Вариант первый:
!!! На малине в принципе все начинает работать сразу из коробки и настройка не требуется.
apt install -y xrdp
Вариант второй:
Чтобы решить эту проблему "второй сессии" и разрешить столько сессий, сколько вам нужно, отредактируйте /etc/xrdp/startwm.sh
и добавьте эти строки перед строками, которые проверяют и запускают Xsession. $HOME/.profile не является частью решения,
но это то, что должно быть запущено перед началом сессии в любом случае.
unset DBUS_SESSION_BUS_ADDRESS
unset XDG_RUNTIME_DIR
. $HOME/.profile
Вариант третий:
Еще в борьбе с белым экраном предлагают удалить пользователя из группы video и render
sudo gpasswd -d video
sudo gpasswd -d render
Вариант четвертый:
Eще скрипт установки у людей на raspberry pi
# Install updates
sudo apt update
sudo apt upgrade -y
# Install and configure xRDP
sudo apt install -y xrdp
sudo systemctl enable xrdp
sudo sed -i 's/"DRMDevice" "[[:alnum:]/]+"/"DRMDevice" ""/g' /etc/X11/xrdp/xorg.conf
sudo gpasswd -d $USER video
# Reboot the machine
sudo reboot
Вариант пятый:
P.s. Многие пишут что вообще ничего не трогают и все работает
кто то удаляет из группы video и тоже начинает работать
а самое главное вообще не трогают startwm.sh
Вариант шестой:
apt-get install xserver-xorg-legacy
vim /etc/X11/Xwrapper.config
----------------------------
allowed_users=anybody
needs_root_rights=yes
----------------------------
Вариант седьмой:
Ошибки dbus
Ставим:
sudo apt install dbus-x11
От пользователя выполняем:
dbus-launch
Вариант восьмой:
https://forums.raspberrypi.com/viewtopic.php?t=387334
Включаем X Activate X11 Server over Wayland on raspi-config utility That's important
Редактируем файл:
Edit /etc/X11/xrdp/xorg.conf
Section "Screen"
Identifier "Screen (xrdpdev)"
Device "Video Card (xrdpdev)"
GPUDevice "Video Card (xrdpdev)" <-- Add this to section...
Monitor "Monitor"
общие команды:
logout - Быстрый выход из сессии интерфейса командной строки config, global-viewconfig
do - Выполнение команды глобального режима CLI (command_sequence) без выхода из режима конфигурирования config
root - Выход на верхний уровень режима конфигурирования config
end - Выход из любого уровня режима конфигурирования в глобальный режим config
quit - Выход из сессии интерфейса командной строки global-view
В глобальном режиме интерфейса командной строки доступны команды просмотра оперативного состояния системы (show-команды),
команды управления компонентами системы (например, reload, hw-module),
запуска различных диагностических тестов и работы с образами операционной системы.
Для уменьшения объема отображаемых данных в ответ за запросы пользователя и облегчения поиска необходимой информации можно воспользоваться фильтрацией.
Для фильтрации вывода команд нужно добавить в конец командной строки символ "|" и использовать одну из опций фильтрации:
formal — модификация выводов "show running-config" и "show candidate-config" из древовидного в линейный
begin — выводить всё после строки, содержащей заданный шаблон
include — выводить все строки, содержащие заданный шаблон
exclude — выводить все строки, не содержащие заданный шаблон
count — произвести подсчёт количества строк в выводе команды.
без конфигуре global-view :
rootshell - попасть в linux shell :)
show interfaces description - показать статус интерфейсов
show running-config - показать конфигурацию устройства
show candidate-config - Вывести кандидат-конфигурацию устройства.
configure - Перейти из глобального режима CLI в режим конфигурирования.
в configure:
commit - Применить кандидат-конфигурацию(применить изменения, внесенные во время сеанса редактирования).
abort - Отменить изменения в кандидат конфигурации и выйти из режим конфигурирования.
При выполнении этой команды кандидат-конфигурация становится идентичной текущей (стартовой) конфигурации.
Тип интерфейса:
Физические интерфейсы:
Обозначение физического интерфейса включает в себя его тип и идентификатор.
Идентификатор имеет вид //, где:
- номер устройства в кластере устройств;
- номер модуля в составе устройства;
- порядковый номер интерфейса данного типа в модуле.
Интерфейсы 10Гбит/с Ethernet tengigabitethernet // tengigabitethernet 0/0/10 te 0/0/10
Интерфейсы 40Гбит/с Ethernet fourtygigabitethernet // fourtygigabitethernet 0/0/2 fo 0/0/2
Интерфейсы 100Гбит/с Ethernet hundredgigabitethernet // hundredgigabitethernet 0/0/3 hu 0/0/3
Физические интерфейсы всегда присутствуют в системе.
Группы агрегации каналов bundle-ether bundle-ether 8
Группы агрегации каналов в системе можно создавать и удалять.
Сабинтерфейсы
bundle-ether .
tengigabitethernet //.
fourtygigabitethernet //.
hundredgigabitethernet //.
Сабинтерфейсы в системе можно создавать и удалять.
Интерфейсы локальной петли loopback loopback 100
Интерфейсы локальной петли в системе можно создавать и удалять.
Интерфейсы управления mgmt //
Интерфейсы out-of-band управления - это выделенные ethernetинтерфейсы для доступа и управления маршрутизатором.
В качестве могут выступать 'fmc0' и 'fmc1', в зависимости от аппаратной конфигурации.
'mgmt 0/fmc0/1' - для ME5100
'mgmt 0/fmc0/0' и 'mgmt 0/fmc0/1' для FMC0 в маршрутизаторе ME5000
'mgmt 0/fmc1/0' и 'mgmt 0/fmc1/1' для FMC1 в маршрутизаторе ME5000
Интерфейсы управления всегда присутствуют в системе.
IMPORTANT
Интерфейсы управления не предназначены для передачи транзитного трафика (не участвуют в работе dataplane) и жестко прикреплены к VRF 'mgmt-intf'.
change-privilege Данной командой осуществляется переход на соответствующий уровень привилегий.
change-privilege { p1 | p2 | … | p15 } [ PASSWORD ]
change-privilege p15 mypassword
clear alarm - Данная команда очищает активные аварии в системе.
clear alarm {all | ID }
all — очищаются все активные аварии
ID — очищается авария с указанным идентификатором.
clear alarm 300
clear arp - Данная команда удаляет записи из ARP-таблицы.
address IPv4 — очищается запись при совпадении IPv4-адреса
interface IF — очищаются записи на указанном интерфейсе
vrf VRF — указание VRF, из которого будет браться ARP-таблица
clear arp vrf test 10.0.0.200
clear bgp - Данная команда изменяет состояние BGP-сессии и счётчиков.
clear bgp {{ vrf ARGS | neighbor ARGS} {counters | flap-statistics |soft ARGS}}
vrf VRF — указание VRF, в котором будет выполнятся действие
neighbor {all | ipv4 | ipv6 | IPv4 | IPv6 } — сброс BGP-сессии: всех, всех ipv4/ipv6 unicast или конкретного адреса соседа
counters — очистка счётчиков BGP-сообщений
flap-statistics — очистка счётчиков flap-statistics
soft in|out — реконфигурация маршрутов(in — восстановить свои маршруты, out — отправить соседу свои маршруты).
clear bgp neighbor 10.0.0.10
clear configuration backups - Удаление бэкап-конфигруации.
clear configuration backups [ String ] - String — указание имени backup-файла.
clear configuration backups
clear crash-info all - Удаление логов crash-info.
clear crash-info { all | String }
clear domain-cache - Сброс кэша доменных имён.
clear domain-cache { String }
clear domain-cache eltex-co.ru
clear flow monitor - Сброс статистики потоков.
clear ipv6 neighbors - Данная команда удаляет записи из NDP-таблицы.
clear ipv6 neighbors address 2005:1::1
clear logging - Данная команда очищает файлы системных логов
persistent — указание на очистку лог-файлов, хранящихся в постоянной памяти
system — указание на очистку control-plane лог-файлов
file WORD — указание имени persistent-логов
clear logging persistent file BGP_LOG
clear mpls - Данная команда сбрасывает состояния LDP-сессий и RSVP-сессий и меток.
clear mpls ldp neighbor all
clear ospfv2 - Данная команда сбрасывает состояния OSPFv2-соседств.
clear ospfv2 statistics
clear ospfv3 - Данная команда сбрасывает состояния OSPFv3-соседств.
clear ospfv3 statistics
clear pim - Данная команда сбрасывает состояния PIM-соседств и очищает топологию.
clear pim counters
clear qos counters - Команда сбрасывает счётчики срабатывания политик QoS.
clear qos counters interface te 0/0/2
dir - Данная команда выводит список файлов со смонтированного USB-носителя.
delete - Данная команда удаляет файл на смонтированном USB-носителе
show system - Выведет текущие общие состояние
show system resources cpu - Данной командой осуществляется просмотр информации о текущем использовании процессора устройства.
show system resources cpu
show version - покажет текущую версию
backup to tftp://192.168.16.113/backup_directory/ - Команда создает элемент резервирования конфигурации и переходит в режим настройки этого элемента.
fan lower-speed 60 - Данной командой устанавливается минимальная скорость вращения вентиляторов системы охлаждения устройства, в процентах.
flow rate - Команда позволяет ограничить полосу пропускания для заданного типа трафика, перехватываемого на процессор.
configure
system punt rate-limit
flow ip-ttl rate 100
commit
broadcast-client - Данной командой включается режим приёма широковещательных сообщений NTP-серверов, при этом устройство работает в качестве NTP-клиента.
ntp vrf mgmt-intf
broadcast-client
clock read-calendar - Данная команда синхронизирует значение программных часов системы со значением аппаратных часов.
clock read-calendar
clock update-calendar - Данная команда записывает в аппаратные часы устройства значение программных часов.
clock update-calendar
ntp vrf Команда включает протокол ntp в заданном vrf и переходит в режим его конфигурирования
ntp vrf mgmt-intf
Интервала времени между отправкой сообщений NTP-серверу
maxpoll - Данная команда устанавливает максимальное значение интервала времени между отправкой сообщений NTP-серверу.
Использование отрицательной формы команды устанавливает значение по умолчанию (10, что соответствует 1024 секундам).
minpoll - Данная команда устанавливает минимальное значение интервала времени между отправкой сообщений NTP-серверу.
Использование отрицательной формы команды устанавливает значение по умолчанию (6, что соответствует 64 секундам).
ntp vrf default
server ipv4 192.168.16.36
maxpoll 15
minpoll 3
peer ipv4 - Данная команда используется для установления партнерских отношений между NTP-серверами и перехода в командный режим config-ntp-vrf-peer-ipv4.
ntp vrf default
peer ipv4 192.168.16.36
prefer - Данная команда отмечает текущий NTP-сервер как предпочтительный.
ntp vrf default
server ipv4 192.168.16.36
prefer
show clock - Данная команда выводит текущее время и дату.
tcp - Данная команда устанавливает режим работы по протоколу TCP для текущего удаленного сервера журналирования и задает номер используемого порта.
logging host 10.7.32.4 vrf default
tcp 513
udp - Данная команда устанавливает режим работы по протоколу UDP для текущего удаленного сервера журналирования и задает номер используемого порта.
logging host 10.7.32.4 vrf default
udp 513
ip mtu - Данная команда позволяет установить в конфигурации правило для задания IPv4/IPv6 Maximum Transmission Unit (MTU).
interface tengigabitethernet 0/0/1
ip mtu 6000
mtu - Данная команда позволяет установить в конфигурации правило для задания Layer 2 Maximum Transmission Unit (L2 MTU).
interface tengigabitethernet 0/0/1
mtu 1700
shutdown - Данная команда позволяет создать в конфигурации правило для административного выключения интерфейса и перевода его в состояние administratively down.
interface tengigabitethernet 0/0/1.100
shutdown
speed - Данная команда позволяет задать режим скорости на Ethernet-интерфейсе.
Отрицательная форма команды возвращает значение по умолчанию (auto).
speed { 10 | 100 | 100G | 10G | 1G | 40G | 25G |auto }
no speed
interface tengigabitethernet 0/0/1
speed 1G
vrf Данная команда позволяет создать в конфигурации экземпляр VRF и перейти в режим его конфигурации (config-vrf).
vrf test
vrf - Данная команда относит интерфейс к указанной Virtual Routing & Forwarding сущности (VRF).
interface tengigabitethernet 0/0/1
vrf TEST
description - Данная команда позволяет задать в конфигурации описание для текущего VRF
vrf test
description test
maximum prefix - Данная команда позволяет ограничить максимальное количество маршрутов в данном VRF.
vrf test
maximum prefix 100
rd - Данная команда позволяет задать в конфигурации Route Distinguisher для данного VRF.
vrf test
rd 10.0.0.1:200
show vrf - Данная команда отображает информацию по активным VRF.
show vrf test
vpn-id - Данная команда задает в конфигурации VRF определенный VPN ID, как описано в RFC 2685.
vrf test
vpn-id 100:100
Часто используемые настройки:
Пример задать имя, время, баннер:
configure
hostname NEW-HOSTNAME
clock set 12:00:00 nov 8 2023
banner exec @ hell0 @
commit
Создание пользователя:
configure
username stepan privilege 1 password password
enable password level 15 godemode
privilege exec 1 show running-config
exec 1 configure
commit
Конфигурация ip адреса для интерфейса:
interface GigabitEthernet 1/0/20
ip address 10.10.10.20/24
Конфигурация ip адреса для vlan:
interface vlan 1
ip address 150.20.137.40/24
Создание vlan для интерфейса:
configure
vlan database
vlan 20 name test
interface GigabitEthernet 1/0/1
switchport access vlan 20
commit
Создание/удаления trank vlan:
configure
interface GiggabitEhernet 1/0/1
switchport mode trunk
switchport trunk allowed vlan 10 - если не указать то затрет все vlan и оставит 10
switchport trunk allowed vlan add 10
switchport trunk allowed vlan add 12
switchport trunk allowed vlan add 20-50
switchport trunk allowed vlan remove 10 - для удаления vlan 10
switchport trunk allowed vlan all - разрешает все вланы
commit
Создание voice vlan:
voice vlan oui-table add a8f94b ( первые три байта телефона который мы в войс отправляем)
voice vlan id 10
voice vlan state oui-enable
lldp med network-policy 1 voice vlan 10 vlan-type tagged up 4
interface gigabitethernet 1/0/1
switchport mode general
voice vlan enable
lldp med enable network-policy
lldp med network-policy add 1
switchport general allowed vlan add 20 untagged
switchport general pvid 20
Создание STP:
spanning-tree
spanning-tree mode rstp (включен по умолчанию)
spanning-tree priority {0-61440}
interface GigabitEthernet 1/0/1
spannig-tree cost {1-200000000} - стоимость
spanning-tree disable - выключить rstp
spanning-tree bpdu filtering
spanning-tree bpduguard enable
Защита вланов rapid-pvst:
spanning-tree
spanning-tree mode rapid-pvst (в cisco по умолчанию включено)
vlan 10-20
interface gigabitethentet 1/0/1
switchport mode trunk
switchport trunk allowed vlan add 10-20
Конфигурация VRRP:
interface vlan 100
ip address 172.16.2.2/24 ( на другом устройстве указываем 172.16.2.3 )
vrrp 100 ip 172.16.2.1
vrrp 100 priority 1
vrrp 100 preempt
no vrrp 100 shutdown - отключить
Настройка dhcp server:
ip dhcp server
ip dhcp pool network Test
address low 10.0.1.100 high 10.0.1.150 255.255.255.0
default-route 10.0.1.1
dns-server 10.0.1.1
ip dhcp exluded-address 10.0.1.120 - исключить адрес
exit
interface vlan 10
ip address 10.0.1.1/24
interface GigaEthernet 1/0/11
switchport access vlan 10
Настройка OSPF:
interface vlan 1
ip address 192.168.1.10/24
exit
router ospf 1 - здесь указываем роутер id
router-id 192.168.1.10
network 192.168.1.10 area 0.0.0.0
redistribute connected subnets
Настройка do1x:
dot1x system-auth-control
aaa authentication dot1x default radius none
radius-server host 10.0.1.2 key eltex
interface gigabitethernet1/0/1
switchport access vlan 500
switchport mode access
dot1x host-mode multi-sessions
dot1x port-control auto
dot1x reauthentication
dot1x timeout tx-period 30
Шторм контроль:
errdisable recovery cause storm-control
interface gigabitethernet1/0/3
storm-control broadcat level 15 trap shutdown
storm-control unicast pps 12500 trap shutdown
storm-control multicast kbps 20480 trap shutdown
Борьба с петлями:
loopback-detection enable
loopback-detection mode {src-mac-addr|base-mac-addr|multicast-mac-addr|broadcast-mac-addr}
loopback-detection interval {1-60}
interface gigabitethernet 1/0/1
loopback-detection enable - включаем собстенно
errdisable recovery cause loopback-detection - обратно включаем если петля
Включение защиты порта:
interface GigabitEthernet 1/0/1
port security mode max-address - ограничиваем кол-во адресов
port security max 10
port security discadr trap 100
Включение защиты dhcp-snooping:
ip dhcp snooping
ip dhcp snooping vlan 10
interface gigabiteyhernet 1/0/1
ip dhcp snooping trust
Включение IP secure Guard:
ip dhcp snooping
ip dhcp snooping vlan 1 - для влана
ip source guard
interface gigabitethernet 0/1 для интерфейса
ip source guard
Настройка статической маршрутизации:
Настройка статической маршрутизации:
Статическая маршрутизация — это механизм, при помощи которого в системе можно вручную создавать, удалять и модифицировать IP-маршруты.
Статические маршруты могут быть заданы как в глобальной таблице маршрутизации, так и внутри VRF.
action Задание действия для пакетов для данного маршрута при маршрутизации трафика.
Отрицательная форма команды устанавливает значение по умолчанию (forward).
action { discard | forward | local | reject}
no action
discard — отбросить пакеты, редистрибуция разрешена
forward — отправить пакеты по маршруту
local — отбросить пакеты, редистрибуция запрещена
reject — не инсталлировать маршрут
router static
address-family ipv4 unicast
destination 40.10.0.0/16 40.10.0.1
interface tengigabitethernet 0/0/7
action reject
destination - Создание статического маршрута в конфигурации семейства AFI/SAFI.
Отрицательная форма команды удаляет заданный статический маршрут.
[no] destination { IPv4_pref | IPv6_pref } { IPv4_nhop | IPv6_nhop }
IPv4_pref (X.X.X.X/N) — IPv4 префикс маршрута
IPv6_pref (X:X:X:X::X/N) — IPv6 префикс маршрута
IPv4_nhop (X.X.X.X) — IPv4 адрес следующего узла (nexthop) для маршрута
IPv6_nhop (X:X:X:X::X) — IPv6 адрес следующего узла (nexthop) для маршрута
router static
address-family ipv4 unicast
destination 40.10.0.0/16 40.10.0.1
interface - Команда принудительно задает интерфейс, через который будет направлен трафик по данному статическому маршруту,
и производит переход в режим настройки дополнительных параметров статического маршрута.
Отрицательная форма команды удаляет данный интерфейс из текущего маршрута.
router static
address-family ipv4 unicast
destination 40.10.0.0/16 40.10.0.1
interface tengigabitethernet 0/0/7
router static - Включение поддержки статической маршрутизации и переход в режим настройки статических маршрутов.
tag - Задание тега маршрута. Данный тег является внутренним параметром маршрута, который может быть использован в дальнейшем, например, в правилах редистрибуции.
router static
address-family ipv4 unicast
destination 40.10.0.0/16 40.10.0.1
tag 3
OSPF
Настройка динамической маршрутизации OSPF
Существует три версии протокола OSPF:
v1 — в данный момент практически нигде не используется
v2 — используется для обмена маршрутной информацией протокола IPv4
v3 — используется для обмена маршрутной информацией протокола IPv6
address-prefix - Данная команда позволяет отфильтровать OSPFv2 IP LFA FRR маршруты в правиле lfa filter по префиксу, для которого будет рассчитываться альтернативный маршрут.
router ospfv2 PROCESS_NAME
lfa filter FILTER
address-prefix 10.0.0.0/8
advertise-max-metric - Команда устанавливает максимальную метрику для non-stub линков на период вермени, заданный командой time-to-advertise
router ospfv2 PROCESS_NAME
advertise-max-metric
area - Данная команда создает в конфигурации устройства определенную зону OSPFv2 и позволяет перейти в режим настройки конфигурации этой зоны.
В режиме конфигурации зоны возможно, в первую очередь, непосредственно конфигурировать интерфейсы, которые будут участвовать в процессе маршрутизации OSPFv2.
[no] area AREA
router ospfv2 PROCESS_NAME
area 0.0.0.0
area-aggregate - Данная команда позволяет создать в конфигурации правило для суммарного маршрута с LSA Type 3 или LSA Type 7.
[no] area-aggregate { nssa-external-lsa | summary-lsa } IPv4_PREFIX_FORMAT
area-id - Команда задает номер области (Area ID) для маршрута, анонсируемого командой host.
no area-id - Отрицательная форма команды удаляет настройку.
router ospfv2 PROCESS_NAME
host 10.10.10.10
area-id 10.0.0.0
as-br disable - Данная команда выключает в данном OSPFv2-процессе функционал Autonomous System Border Router (ASBR).
router ospfv2 PROCESS_NAME
as-br disable
authentication-key - Данная команда создает в конфигурации ключ аутентификации OSPF сессий на указанном интерфейсе.
router ospfv2 PROCESS_NAME
area 0.0.0.0
interface tengigabitethernet 0/0/1
authentication-key test
authentication-type - Команда задает тип шифрования, используемый при аутентификации.
router ospfv2 PROCESS_NAME
area 0.0.0.0
interface tengigabitethernet 0/0/1
authentication-type md5
auto-cost reference-bandwidth - Команда задает референсное (максимальное) значение пропускной способности (bandwidth),
относительно которого будет высчитываться стоимость интерфейса.
Стоимость интерфейса с референсным значением будет равна единице.
router ospfv2 PROCESS_NAME
auto-cost reference-bandwidth 1000000
bandwidth - Команда задает значение пропускной способности (bandwidth) на интерфейсе, которое будет использовано
при подсчете стоимости (cost) данного интерфейса относительно референсного значения.
router ospfv2 PROCESS_NAME
area 0.0.0.0
interface tengigabitethernet 0/0/1
bandwidth 100000
dead-interval - Данная команда позволяет задать в конфигурации значение OSPF Dead Interval.
router ospfv2 PROCESS_NAME
area 0.0.0.0
interface tengigabitethernet 0/0/1
dead-interval 10
disable - Данная команда запрещает добавление отфильтрованных OSPFv2 IP LFA FRR маршрутов при использовании фильтра lfa filter.
router ospfv2 PROCESS_NAME
lfa filter FILTER
disable
dscp - Команда указывает значение DSCP для исходящих сообщений OSPF протокола.
router ospfv2 1
area 0.0.0.0
interface twentyfivegigabitethernet 0/0/2
dscp 32
effect - Команда указывает значение DSCP для исходящих сообщений OSPF протокола.
router ospfv2 PROCESS_NAME
area 0.0.0.0
area-aggregate summary-lsa 10.0.0.0/8
effect advertise-matching
external-lsa-refresh-interval - Команда задает интервал между обновлениями external LSA, принадлежащих маршрутизатору.
router ospfv2 PROCESS_NAME
external-lsa-refresh-interval 60
Настройка LACP / LAG
Рассмотрим настройку LACP-группы в режиме active.
В режиме active порты коммутатора являются инициаторами согласования по протоколу LACP.
На встречной стороне порт должен быть настроен как в режиме active, так и в режиме passive.
Необходимо выполнить следующее:
1) Включаем работу LAG глобально на коммутаторе:
configure terminal
set port-channel enable
2) Активируем группу, в которую будем включать интерфейсы:
interface port-channel 2
no shutdown
exit
3) Перейти в режим конфигурирования порта:
interface GigabitEthernet0/2
4) Настроить LACP-группу:
channel-group 2 mode active , где 2 – номер группы
active – добавить порт в LACP-группу в режиме active.
для роутера:
lacp
interface bundle-ether 1
exit
interface tengigabitethernet 0/0/3
bundle id 1
bundle mode active
exit
interface tengigabitethernet 0/0/7
bundle id 1
bundle mode active
exit
exit
Существует 5 типов пакетов протокола OSPF, которые позволяют устанавливать соседство и выполнять обновление маршрутной информации:
Type 1 — Hello. Обнаруживает соседей и поддерживает соседские отношения.
Type 2 — Database Description. Описывает содержимое базы данных состояния канала маршрутизатора.
Type 3 — Link State Request (LSR). Запрос на получение базы данных состояния канала.
Type 4 — Link State Update (LSU). Обновление базы данных состояния канала (передача LSA соседним маршрутизаторам).
Type 5 — Link State Acknowledgment (LSAck). Подтверждение получения обновления.
Каждый пакет Link State Update, генерируемый маршрутизатором, содержит один или несколько LSA. Существует 5 различных типов LSA:
Type 1 — Router-LSA.
Генерируется каждым маршрутизатором для каждой области, которой он принадлежит.
Он описывает состояние интерфейсов маршрутизатора, подключенных к этой области.
Type 2 — Network-LSA.
Генерируется назначенным маршрутизатором (DR).
Он описывает набор маршрутизаторов, подключенных к определенной сети.
Рассылается только в области, содержащей эту сеть.
Type 3 или 4 — Summary-LSA.
Описывают маршруты между областями.
Type 3 Summary-LSA генерируются ABR и описывают маршруты между ABR и внутренними маршрутизаторами локальной области.
Они рассылаются через магистраль другим ABR.
Type 4 Summary-LSA описывают маршруты к ASBR.
Type 5 - AS-external-LSA.
Генерируются ASBR и описывают маршруты к пунктам назначения за пределами автономной системы.
Маршрут по умолчанию для автономной системы также описывается AS-external-LSA
Команды для диогностики ospf
MES5324:
общая инфа:
show ip ospf
соседи:
show ip ospf neighbor
обмен:
show ip ospf database
ME5200
общая инфа:
show ospfv2
соседи:
show ospfv2 neighbors
обмен:
show ospfv2 database
lacp MES5324 + MES5324:
Настройки sw1
interface tengigabitethernet1/0/2
channel-group 5 mode auto
exit
!
interface tengigabitethernet1/0/3
channel-group 5 mode auto
exit
!
interface tengigabitethernet1/0/5
channel-group 5 mode auto
exit
!
interface tengigabitethernet1/0/6
channel-group 5 mode auto
exit
!
interface Port-channel5
ip address 10.0.50.1 255.255.255.0
exit
Настройки sw2
interface tengigabitethernet1/0/2
channel-group 5 mode auto
exit
!
interface tengigabitethernet1/0/3
channel-group 5 mode auto
exit
!
interface tengigabitethernet1/0/5
channel-group 5 mode auto
exit
!
interface tengigabitethernet1/0/6
channel-group 5 mode auto
exit
!
interface Port-channel5
ip address 10.0.50.2 255.255.255.0
exit
lacp MES5324 + ME5200S:
Настройка MES5324:
interface tengigabitethernet1/0/1
channel-group 2 mode auto
exit
!
interface tengigabitethernet1/0/7
channel-group 2 mode auto
exit
!
interface Port-channel2
ip address 10.0.10.2 255.255.255.0
exit
Настройка ME5200S:
lacp
interface bundle-ether 1
exit
interface tengigabitethernet 0/0/3
bundle id 1
bundle mode active
exit
interface tengigabitethernet 0/0/7
bundle id 1
bundle mode active
exit
exit
!
interface bundle-ether 1
ipv4 address 10.0.10.1/24
exit
тесты кабеля
Показать интерфейсы:
show interfaces status
Тест медного кабеля:
test cable-diagnostics tdr interface gi0/1
Показать длину медного кабеля:
show cable-diagnostics cable-length
Показать оптические интерфейсы:
show fiber-ports optical-transceiver
show fiber-ports optical-transceiver interface TengigabitEthernet1/0/7
show fiber-ports optical-transceiver detailed interface TengigabitEthernet1/0/7
Зеркало трафика:
monitor session 1 destination interface gi1/0/3 - куда перенаправить трафик
monitor session 1 source interface gi1/0/2 both - откуда откуда перенаправить трафик
mpls
mpls label = 32 bit
layer2 Header | MPLS Header | IP Packet
MPLS Header:32 Bits (4 Bytes)
The label Value | Exp | S | TTL
20 bits | 3 bits | 1 bits | 8 bits
1 - 1 048 576 | 8 значений | два значения 0 или 1 | 0-255
Стак S
Первый пришёл последний вышел FILO
Fist IN / Fist OUT
0 - еще будет mpls label
1 - все последний mpls label
LSR - LABEL SWITCH ROUTER
Ingress LSR (imposition) - получает IP пакет, пушит в него MPLS Label(stack)
Следовательно вылетает из него MPLS пакет
Egress LSR (disposition) - получает MPLS пакет, удаляет из него лейбл.
Следовательно вылетает из него уже IP пакет.
Ingress/Egress LSR - находятся по краям (edge)mpls сети.
Часто их называют PE(provider edge) устройствами
Intermediate LSR - получает MPLS пакет, производит операции над ним и отправляет MPLS трафик дальше.
Часто называются P (Provider) устройствами
ip -> LSR -> ip = IP FORWARDING
mpls -> LSR -> mpls = INTERMEDIA LSR (P - provider)
mpls -> LSR -> ip = EGRESS LSR
ip -> LSR -> mpls = INGRESS LSR
CE ->> PE --> MPLS(P) <-- PE <--CE
CE - Costome Edge (оборудование которое ничего не знает про MPLS)
PE - Provider Edge ( на границе сети ) (Оборудование которое как то взаимодействует с MPLS, например ip -> mpls)
P - Provider Router ( внутри сети) (оборудование общающееся исключительно через MPLS)
imposition - добавление метки mpls
desposition - убирание метки mpls
LABEL SWITCH PATH (LSP). FEC
LSP - это простой список из LSR которые коммутируют MPLS пакет через всю MPLS сеть, либо через часть MPLS сети
Forwarding Equivalence Class (FEC) - группа пакетов которые коммутируются по одному и тому же пути и обслуживают одинаково
Все пакеты принадлежавшие одному FEC будут иметь один и тот же лейбл.
При этом пакеты с одним и тем же лейблом не всегда принадлежат к одному FEC, например, в случае если их mpls EXP отличаются.
Ingress LSR принимает решения о том, к каким FEC принадлежат приходящие в него пакеты.
LFIB - база меток mpls (Label Forwarding instance(information)Base
Содержит ipv4/ipv6 prefix, VPN prefix, TE tunnel, l2 forwarding entry, local label, remote label
85 17 eth1
11 22 eth2
13 33 eth3
Local Label - метка, которую локальный LSR назначил на префикс
Remote Label - метка, которую LSR получил от соседнего LSR
Протоколы получения лейблов:
1. Static ( возможность есть, но никогда так не делай! )
2. LDP ( сам все сделал, сам настроил )
3. RSGP-TE ( можно явно задать хождение трафика ) / Trafic Engineering
4. BGP
5. SR - mpls
SRv6
(модное под капотом OSPF/ISIS)
LDP = LABEL DISTRIBUTION PROTOCOL
назначает лейблы на все префиксы в таблице маршрутизации и передает соседям label binding
Prefix+label=binding
Labal binding передается соседям автоматически без каких то дополнительных запросов
SWAP - замена лейбла на другой
PUSH - был ip пакет ушел mpls
POP - был mpls ушел ip
Включение mpls на cisco
mpls ldp router-id lo0
mpls ip
int gi 0/0
mpls ip
show mpls forwarding-table
show ip route
Включение mpls на eltex ME5200S
mpls
forwarding
interface loopback 1
interface tengigabitethernet 0/0/4
exit
ldp
discovery interface tengigabitethernet 0/0/4
exit
neighbor 10.50.50.4 - сосед
exit
exit
router-id 10.50.50.1 - наш ип на loopback
transport-address 10.50.50.1 - наш ип на loopback
exit
show mpls ldp forwarding - покажет метки
show mpls ldp bindings local - покажет распределение меток локально
show mpls ldp bindings remote - покажет распределение меток удаленных
show mpls ldp bindings mldp - покажет распределение меток
sh run cluster
sh run bridges 100
bridge 100
vlan 1
ip firewall disable !!! ПОтотм включим как убедимся что заработало
ip фввкуыы 192.168.100.1/24
unit 1
ip address 192.168.100.2/24
unit 2
vrpp forse-up
vrrp id 100
vrrp 192.168.100.100/24
vrrp group 1
vrrp preempt disable
vrrp timers garp refrash 1
vrrp
enable
exit
Проверка
show cluster status
show cluster sync status
Интерфесы на первом юните нумеруется 1/0/1 а на втором 2/0/1
sh run int gi 1/0/1 - покажет первый юнит
sh run int gi 2/0/1 - покажет второй юнит
bridge 20
vlan 20
security-zone trusted
ip address 172.16.1.2/24 unit 1
ip address 172.16.1.3/24 unit 2
vrrp id 20
vrrp ip 172.16.1.1/24
vrrp group 1
vrrp timers garp refrash 1
vrrp
enable
exit
object-group network sync_dst
ip address-range 192.168.100.2 unit 1
ip address-range 192.168.100.1 unit 2
exit
object-group network sync_src
ip address-range 192.168.100.1 uni1
ip address-range 192.168.100.2 unit2
exit
по поводу фаервола:
sh run failovers
ip failover
local-address object-group sync_src
remote-address object-group sync_dst
vrrp-group 1
exit
ip firewall failover
sync-type unicast
port 9999
enable
exit
ip dhcp-server failover
mode active-standby
enable
exit
crypro-sync
enable
exit
Проверка доступных сервисов:
show higj-availability state
Включение фаервола:
Проверяем сессии:
show ip firewall sessions inside-source-address 192.168.100.1
0. Создаем директорию для проекта
mkdir ИМЯ_ПРОЕКТА
cd ИМЯ_ПРОЕКТА
touch main.go
1. Первичная иницилизация
go mod init ИМЯ_ПРОЕКТА
2. Докача модулей из интернета
go get путь_до_модуля
go get путь_до_модуля
go get путь_до_модуля
go get путь_до_модуля
Сборка:
go build -o ИМЯ_ПРОЕКТА_ЖЕЛАЕМОЕ_ИМЯ_БИНАРНИКА_Х86
GOOS=linux GOARCH=arm64 go build -o ИМЯ_ПРОЕКТА_АРМ64
P.S.
ИМЯ_ПРОЕКТА/
│── go.mod # Файл с информацией о модулях
│── go.sum # Контрольные суммы зависимостей
│── main.go # Исходный код
└── ИМЯ_ПРОЕКТА # Скомпилированный бинарник (после go build)
pacman -Syu - Полное обновление системы: синхронизирует базы данных пакетов и обновляет все установленные пакеты до последних версий.
pacman -Sy - Синхронизирует базы данных пакетов (обновляет список доступных пакетов), но не устанавливает обновления.
pacman -Su - Обновляет установленные пакеты до последних версий (без синхронизации баз).
pacman -Syu - стандартная команда для поддержания системы в актуальном состоянии.
Установка пакетов:
pacman -S <имя_пакета> - Устанавливает указанный пакет и его зависимости.
pacman -S <пакет1> <пакет2> - Устанавливает несколько пакетов за раз.
Пример:
pacman -S htop - устанавливает утилиту htop для мониторинга процессов.
Удаление пакетов:
pacman -R <имя_пакета> - Удаляет указанный пакет, оставляя его зависимости.
pacman -Rs <имя_пакета> - Удаляет пакет и его зависимости, если они больше никому не нужны.
pacman -Rns <имя_пакета> - Удаляет пакет, зависимости и их конфигурационные файлы (более полное удаление).
Пример:
pacman -Rs htop — удаляет htop и ненужные зависимости.
Поиск пакетов:
pacman -Ss <ключевое_слово> - Ищет пакеты по ключевому слову в репозиториях (включая описание).
pacman -Qs <ключевое_слово> - Ищет установленные пакеты по ключевому слову.
Пример:
pacman -Ss firefox — ищет пакеты, связанные с Firefox.
Информация о пакетах:
pacman -Si <имя_пакета> - Показывает информацию о пакете из репозитория (версия, зависимости и т.д.).
pacman -Qi <имя_пакета> - Показывает информацию об уже установленном пакете.
Пример:
pacman -Qi htop — выводит данные об установленном htop.
Очистка системы:
pacman -Sc - Удаляет кэш загруженных пакетов, оставляя только установленные версии.
pacman -Scc - Полностью очищает кэш пакетов.
pacman -Rns $(pacman -Qdtq) - Удаляет "осиротевшие" пакеты (зависимости, которые больше не нужны).
Пример:
pacman -Scc — освобождает место, удалив весь кэш.
pacman -Q - Показывает список всех установленных пакетов.
pacman -Qe - Показывает только явно установленные пакеты (не зависимости).
pacman -Qdt - Показывает осиротевшие пакеты.
Пример:
pacman -Qe — полезно, чтобы понять, что ты сам устанавливал.
Дополнительные полезные флаги:
--noconfirm - Подтверждает все действия автоматически (без вопросов "y/n").
--needed - Не переустанавливает уже установленные пакеты.
Пример:
pacman -S htop --noconfirm — устанавливает htop без подтверждения.
0. Подготовка системы debian/ubuntu:
apt install lz4 vim sudo gawk wget git-core diffstat unzip texinfo gcc-multilib build-essential chrpath socat cpio python3 python3-pip python3-pyelftools python3-pexpect xz-utils debianutils iputils-ping libsdl1.2-dev xterm
1. Опционально, команда python выполняет python3
update-alternatives --install /usr/bin/python python /usr/bin/python3 1
2. Настраиваем локаль:
vim /etc/locale.gen
-------------------
en_US.UTF-8 <---------- найти и раскоментить
------------------
Перечитать local:
locale-gen
На этом все, теперь у вас должна появится local en_US.UTF-8
3. Создаем пользователя например useryocto
useradd useryocto
Входим под пользователем useryocto
su - useryocto
4. Создаем директорию yocto и cкачиваем репазитори napi
mkdir yocto
cd yocto
git clone --depth 1 git://git.yoctoproject.org/poky -b kirkstone
cd poky
git clone --depth 1 git://git.openembedded.org/meta-openembedded.git -b kirkstone
git clone --depth 1 git://git.yoctoproject.org/meta-arm.git -b kirkstone
git clone --depth 1 https://gitlab.nnz-ipc.net/pub/napilinux/meta-influx.git -b kirkstone
git clone --depth 1 https://gitlab.nnz-ipc.net/pub/napilinux/meta-nnz.git -b kirkstone
git clone --depth 1 https://github.com/sbabic/meta-swupdate -b kirkstone
git clone git://git.yoctoproject.org/meta-raspberrypi -b kirkstone
5. После загрузки выполняем
source oe-init-build-env
6. На этом этапе мы можем скопировать настроенные слои
# napi image :
# -- # cp ../meta-nnz/conf/bblayers.conf.sample.napi conf/bblayers.conf
# frontcontrol image:
# -- # cp ../meta-nnz/conf/bblayers.conf.sample.fc conf/bblayers.conf
Я копирую слой для rpi
cp ../meta-nnz/conf/bblayers.conf.sample.rpi conf/bblayers.conf
7. Еще нужно добавить основной конфиг в котором мы в будущем выберем нужную платформу
cp ../meta-nnz/conf/local.conf.sample conf/local.conf
8. Редактируем файл local.conf
vim conf/local.conf
---------------------------
MACHINE ?= "napi-rk3308b-s" <----------------- ищем строку MACHINE
---------------------------
Возможные варианты:
MACHINE ?= "napi-rk3308b-s"
MACHINE ?= "napi-rk3308"
MACHINE ?= "roc-pc-rk3328"
MACHINE ?= "rockpro64-rk3399"
9. Сборка
Возможные варианты сборки:
nnz-frontcontrol-image
nnz-napi-image
nnz-napi-image-dev
nnz-napi-image-dev-noupdate
Пример сборки:
bitbake -k nnz-frontcontrol-image
Загрузка исходников без сборки:
bitbake nnz-frontcontrol-image --runall=fetch
bitbake nnz-napi-image --runall=fetch
bitbake nnz-napi-image-dev --runall=fetch
bitbake nnz-napi-image-dev-noupdate --runall=fetch
Ошибка:
Я собирал от пользователя user и архивы закинул другому пользователю и получил ошибку:
Error, TMPDIR has changed location.
You need to either move it back to /home/user/yocto/poky/build/tmp or delete it and rebuild
Просто удалил файлы сборки из tmp, так как в архиве были нужные исходники для сборки, а самой сборки не производилось.
rm -rf ~/yocto/poky/build/tmp
10. Собранные имеджи искать тут:
~/yocto/poky/build/tmp/deploy/images
11. Учетные данные по умолчанию.
Username: root
Password: napilinux
Прошивка napi (rk3308)
Ссылки:
бутлодеры:
https://dl.radxa.com/rockpis/images/loader/
Образы napi:
https://download.napilinux.ru/linuximg/
Компоненты для rkdeveloptool
sudo apt-get install libudev-dev libusb-1.0-0-dev dh-autoreconf
rkdeveloptool
git clone https://github.com/rockchip-linux/rkdeveloptool
cd rkdeveloptool
autoreconf -i
./configure
make
cp rkdeveloptool /usr/local/bin/
Убедится что нету других rkdeveloptool
whereis rkdeveloptool
Команды rkdeveloptool
rkdeveloptool - справка
rkdeveloptool ld - лист устройств
rkdeveloptool db <файл загрузчика> - загрузка бутлодера
rkdeveloptool wl 0 <файл образа> - загрузка прошивки
Порядок прошивки:
0. нажимаем и удерживаем клавишу Maskrom, затем коротко нажимаем клавишу Reset не отпускаем Maskrom, через несколько секунд отпускаем Maskrom;
1. Грузим бутлодер
sudo rkdeveloptool db rk3308_loader_uart0_m0_emmc_port_support_sd_20190717.bin
Или
sudo rkdeveloptool db rk3308_loader_ddr589MHz_uart0_m0_v2.06.136sd.bin
!!! Если бутлодер не правильный или вы его не загрузили, то получите ошибку: Write LBA failed!
2. Прошиваем прошивку
sudo rkdeveloptool wl 0 <файл образа>
Пример:
rkdeveloptool wl 0 napi-rk3308b-s-latest-dev.img
P.S Очистка nand:
Создаем пустой файл с помощью dd
dd if=/dev/zero of=./zero.img bs=4M count=10
Шьем этим файлом.
rkdeveloptool db <файл загрузчика> - загрузка бутлодера
rkdeveloptool wl 0 zero.img
minicom -D /dev/ttyUSB1 -b15000000
apt install apt-file
apt-file search bin/7z
apt-file update
apt-file show
strace
strace
witch -a date
dpkg -S /bin/date
dpkg -L coreutils
dpkg -s coreutils
Управляющие символы терминала:
нотация ввод вывод клавиши код_символа код_символа
^C intr - Ctrl+C 0x03 EXT
^ quit - Ctrl+ 0x1c FS
^ quit - Ctrl+4 0x1c FS
^Z susp - Ctrl+Z 0x1A SUB
^D eof - Ctrl+D 0x04 EOT
^? erase - Backspace 0x7F DEL
^? erase - Ctrl+? 0x7F DEL
^? erase - Ctrl+8 0x7F DEL
^H - backspace Ctrl+H 0x08 Del
b - backspace Ctrl+H 0x08 Del
^W werase - Ctrl+W 0x17 ETB
^U kill - Ctrl+U 0x15 NAK
^l - tab TAB 0x09 HT
t - tab Ctrl+I 0x09 HT
^M eol cr Enter 0x0D CR
r eol cr Ctrl+M 0x0D CR
^j eol nl Ctrl+j 0x0A LF
n eol nl Ctrl+j 0x0A LF
^S stop - Ctrl+S 0x13 DC3
^Q start - Ctrl+Q 0x11 DC1
^R rprnt - Ctrl+R 0x12 DC2
^V lnext - Ctrl+V 0x16 SYN
^N - so Ctrl+N 0x0E SO
^O - si Ctrl+O 0x0f SI
^[ esc esc ESC 0x1B ESC
e esc esc ESC 0x1B ESC
^[ esc esc Ctrl+[ 0x1B ESC
e esc esc Ctrl+3 0x1B ESC
!!! Обратите внимание на код символа / клавиши / ввод / вывод / натацию !!!
!!! Многие действия можно сделать разными наборам нотация и клавиш !!!
Показать доступные символы для терминала:
stty -a
whoami
strace -fe uname,getcwd,geteuid,sethostname whoami
hostname
strace -fe uname,getcwd,geteuid,sethostname hostname
pwd
strace -fe uname,getcwd,geteuid,sethostname pwd
err
strace -fe uname,getcwd,geteuid,sethostname hostname springfield
date
ltrace -x *time*+fwrite date
Стандарты
Организация IEEE
IEEE 1003.1 POSIX.1 - интерфейс API операционной системы
IEEE 1003.2 POSIX.2 - интерфейс командной строки ОС (CLI)
Posix (Portable Operating System Interface)
SUS (Single UNIX Specification)
Телетайпы
ascii(7)
charset(7)
7 - семибитная кодировка
Управляющие символы:
CR - (carriage return) - Возврат головки к началу строки
BS - (back space) - Перемещение головки справа на лево
LF - (line feed) - Прокрутка бумаги Начало новой строки
LN - (line new) - На новую строку
HT - (Horizantal tab) - На несколько символов вправо
SO - (shift out) - Изменят шрифт на мелкий
SI - (Shift in) - Изменяет шрифт на большой
Виртуальные терминалы:
Когда-то терминалы подключались с помощью RS232 и драйвера ttyS(), сейчас это экзотика.
Узнать к какому терминалу подключены вы используйте команду tty
tty
who
users
w
Переключение между терминалами на лакальном ПК
ALT + F1
ALT + F12
CTRL + ALT + F1
stty
tee
Команда tee используется для того, чтобы одновременно вывести данные на экран и записать их в файл.
Это особенно полезно для сохранения вывода команды в файл без потери возможности видеть вывод в реальном времени.
Запись вывода команды в файл и отображение в терминале
echo "Hello, World!" | tee output.txt
Добавление данных в файл (с флагом -a)
echo "New line" | tee -a output.txt
Запись вывода команды в несколько файлов
echo "Multi-output" | tee file1.txt file2.txt
Использование tee с пайплайнами
ls -l | tee filelist.txt | grep ".txt"
echo -e "onentwonthree" | tee output.txt | wc -l
Использование с перенаправлением стандартного потока ошибок
ls /nonexistent /tmp |& tee output.txt
/pre>
Управляющие последовательности:
whereis date
which date
type date
type -a date
type -a ls
Трассировка выполнения команд в bash
Для влечения достаточно выполнить:
set -x
Для отключения:
set +x
Собственно чем отличается "-" "--"
- опция
-- специальная опция сигнализирует о конце списка опций, за которыми следуют лексемы,
расцениваемые как аргументы вне зависимости от их написания
позволяют навести некий порядок
Справочные системы / MAN
whatis intro
whatis whatis
whatis apropos
whatis man
man -w man
man -w passwd
/usr/share/man/man1/asn1parse.1ssl.gz
/usr/share/man/man1/passwd.1.gz
/usr/share/man/man5/passwd.5.gz
man 5 passwd
man 1 passwd
man asn1parse
Клавиши в man:
q - выход
h - справка
стрелки - переходы
/ - поиск по регулярному выражению вперед
? - поиск назад
n - поиск вперед
N - повторить поиск в обратном направлении
G - в конец страницы
g - в начало страницы
help
help -d date
help -d cd
help -d ls
help -d unset
Пользователи и группы:
UID - User Identifier
GID - Group Identifier
Узнать свой UID GID
id
Передача полномочий:
su - switch user - переключится на пользователя
sudo - switch user do - контролируемая передача полномочий
su - реализует повторную регистрацию в системе
sudo - реализует явные правила передачи полномочий описанных в файле "/etc/sudoers" и подтвердить передачу полномочий с помощью пароля пользователя
Пароли и пользователи группы в файле:
/etc/passwd
/etc/shadow
/etc/group
/etc/gshadow
Переменные окружения:
Посмотреть можно так:
env
printenv
Вывод env:
SHELL=/bin/bash - текущий шел
HOME=/home/username - домашний каталог
LANGUAGE= - язык
LANG=en_US.UTF-8 - язык
PWD=/home/username/1 - текущий каталог
LOGNAME=username - пользователь
USER=username - пользователь
PATH=/usr/local/sbin:/usr/local/bin:/usr/bin - где искать программы
LC_* - наборы переменных определяют другие языковые особенности
LC_TIME - определяет формат вывода даты
PAGER - указывает на программу для постраничного листания например на less / more
EDITOR - имя текущего редактора vim / nano
VISUAL - имя текущего редактора vim / nano
BROWSER - имя html просмоторщика
TERM - устанавливает имя терминала по которому программа использует управляющие символы ESC
locale - список доступных локалей
locale -a
Пример:
export LC_TIME=ru_RU.utf8
date
export LC_TIME=en_US.utf8
date
Переменная PS1 (.bashrc)
Хранит настройки приглашения shell
alias ls='ls --color=auto'
PS1='[u@h W]$ '
u - имя зарегистрированного пользователя в системе
h - короткое собственное имя компьютера
w - имя текущего каталога
$ - символ приглашения ($ обычный # root)
t - время
e - символ управления ESC
и т.д. см "man 5 terminfo"
printenv
printenv TERM
infocmp
Файлы и каталоги:
.profile
.bashrc
.config
.ssh
.nanorc
Файлы и каталоги:
ls -l /bin/ls /dev/sda /dev/tty /sbin/halt
-rwxr-xr-x 1 root root 137920 Aug 30 14:57 /bin/ls
brw-rw---- 1 root disk 8, 0 Sep 19 11:53 /dev/sda
crw-rw-rw- 1 root tty 5, 0 Sep 25 11:28 /dev/tty
lrwxrwxrwx 1 root root 9 Sep 10 18:06 /sbin/halt -> systemctl
ls -la /run/systemd/notify
srwxrwxrwx 1 root root 0 Sep 4 11:39 /run/systemd/notify
ls -la /run/systemd/inaccessible/fifo
p--------- 1 root root 0 Sep 4 11:39 /run/systemd/inaccessible/fifo
- обычный файл
b - блочное устройство (block)
c - символьное устройство (character)
p - именованный канал (pipe)
s - сокет(socket)
l - символьная ссылка (link)
Вот так их можно найти файлы сокетов и именованных каналов
find / -type p
find / -type
file file_name - программа может показать что перед вами за файл, так как файл может быть текстовым или бинарным
stat file_name - подробная статистика о файле
Специальные файловые устройства:
/dev/sd* /dev/input/mouse* /dev/video* /dev/snd/pcm* /dev/dri/card*
crw-rw----+ 1 root video 226, 1 Sep 19 11:53 /dev/dri/card1
crw-rw---- 1 root input 13, 32 Sep 19 11:53 /dev/input/mouse0
brw-rw---- 1 root disk 8, 0 Sep 19 11:53 /dev/sda
brw-rw---- 1 root disk 8, 1 Sep 19 11:53 /dev/sda1
brw-rw---- 1 root disk 8, 2 Sep 19 11:53 /dev/sda2
brw-rw---- 1 root disk 8, 3 Sep 19 11:53 /dev/sda3
brw-rw---- 1 root disk 8, 16 Sep 19 11:53 /dev/sdb
brw-rw---- 1 root disk 8, 17 Sep 19 11:53 /dev/sdb1
brw-rw---- 1 root disk 8, 32 Sep 19 11:53 /dev/sdc
brw-rw---- 1 root disk 8, 33 Sep 19 11:53 /dev/sdc1
brw-rw---- 1 root disk 8, 48 Sep 23 15:34 /dev/sdd
brw-rw---- 1 root disk 8, 64 Sep 23 15:56 /dev/sde
crw-rw----+ 1 root audio 116, 3 Sep 19 16:59 /dev/snd/pcmC0D0c
crw-rw----+ 1 root audio 116, 2 Sep 24 18:10 /dev/snd/pcmC0D0p
crw-rw----+ 1 root audio 116, 4 Sep 19 11:53 /dev/snd/pcmC0D2c
crw-rw----+ 1 root audio 116, 7 Sep 25 12:56 /dev/snd/pcmC1D3p
crw-rw----+ 1 root audio 116, 8 Sep 25 12:56 /dev/snd/pcmC1D7p
crw-rw----+ 1 root audio 116, 9 Sep 25 12:56 /dev/snd/pcmC1D8p
Устройства бывают символьные c и блочные b
Рассмотрим строки:
brw-rw---- 1 root disk 8, 0 Sep 19 11:53 /dev/sda
brw-rw---- 1 root disk 8, 1 Sep 19 11:53 /dev/sda1
brw-rw---- 1 root disk 8, 2 Sep 19 11:53 /dev/sda2
brw-rw---- 1 root disk 8, 3 Sep 19 11:53 /dev/sda3
brw-rw---- 1 root disk 8, 16 Sep 19 11:53 /dev/sdb
brw-rw---- 1 root disk 8, 17 Sep 19 11:53 /dev/sdb1
brw-rw---- 1 root disk 8, 32 Sep 19 11:53 /dev/sdc
brw-rw---- 1 root disk 8, 33 Sep 19 11:53 /dev/sdc1
brw-rw---- 1 root disk 8, 48 Sep 23 15:34 /dev/sdd
brw-rw---- 1 root disk 8, 64 Sep 23 15:56 /dev/sde
Все драйверы ядра пронумерованы главными (major) числами (цифра 8), а под их управлением дополнительные(minor) числа (0,1,2,3,16,17,32,33,48,64)
Еще в linux есть специальные устройства:
/dev/null - всегда пустое
/dev/full - всегда полное
/dev/zero - всегда бесконечно нулевое
/dev/random - генератор псевдо случайных чисел
/dev/urandom - генератор псевдо случайных чисел
Именованные каналы и файловые сокеты:
IPC (InterProcess Communication)
Служат для обмена процессов и программ между собой.
Таким устройством могли бы стать и обычные файлы, но файлы служат для сохранения информации.
pipe они де FIFO-файлы(first in first out) / named pipe
socket
Основное отличие именованного канала от сокета состоит в особенности передачи данных.
Через именованный канал организуется однонаправленная (симплексная) передача без мультиплексирования,
а через сокет - двунаправленная (дуплексная) мультиплексированная передача.
Именованный канал обычно работает по схеме "поставщик - потребитель" (producer-consumer)
Один потребитель принимает информацию от одного поставщика (на самом деле от многих но в разное время)
telinit
init
halt
reboot
shutdown
poweoff
/dev/initctl
/run/initctl
Сокет, схема работы "клиент - сервер" (client-server)
Один сервер принимает и отправляет информацию от многих ко многим (одновременно) клиентам.
cron
cupsd
logger
/dev/log
/run/systemd/journal/dev-log
systemd-journald
Файловые дескрипторы:
Системные вызовы:
open - открытие файла
read - чтение файла
write - запись файла
close - закрытие файла
ioctl - используется для управления драйвером устройств ioctl(input output control), применяется в основном для специальных файлов устройств
При запросе на открытие файла системным вызовом open производится его однократный поиск (относительно медленный поиск) имени файла в дереве каталогов
и для запросившего процесса создается так называемый файловый дескриптор(descriptor).
Файловый дескриптор содержит информацию, описывающую файл, например: индексный дескриптор inode файла на файловой системе,
номера major и minor устройства, на котором располагается файловая система файла, режим открытия файла и прочую служебную информацию.
При последующих операция read и write доступ к самим данным файла происходит с использованием файлового дескриптора(что исключает медленный поиск файла).
Файловые дескрипторы пронумерованы и содержатся в таблице открытых процессом файлов, которую можно получить при помощи диагностической программы lsof.
Получить список процессов, открывающих файл, можно при помощи lsof и fuser
lsof
fuser
lsof -p $$
ls -la /dev/log
sudo lsof /run/systemd/journal/dev-log
sudo fuser /run/systemd/journal/dev-log
ps p 317
sudo lsof /var/log/syslog
ps up 354
Пример с локалью:
strace -fe open,openat,close,read,write,ioctl date
file /etc/localtime
file /usr/share/zoneinfo/Europe/Moscow
Пример с сидюком, где только его взять в 2024году....
ls -la /dev/cdrom
strace -fe open,openat,close,read,write,ioctl eject
Пример с клавишей на клаве и ее светодиодом:
strace -fe open,openat,read,write,close,ioctl setleds -L +num +scroll
Файловые системы и процедура монтирования:
mount
mount /dev/cdrom ~/mnt/cdrom
mount -t iso9660
lsblk -f /dev/cdrom
Сетевые файловые системы:
Файловый сетевой сервер NAS
Network Attached Storage
Протоколы:
NFS(Network File System)
CIFS/SMB (Common Internet file System и Server Message Block
mount -t nfs 10.1.1.1:/share/video /mnt/nas/video
mount -t -cifs -o username=guest //10.1.1.1/share/photos /mnt/nas/photos
Специальные файловые системы:
proc - информация о процессах, нитях и прочих сущностях ядра операционной системы
и используемых ими ресурсах предоставляет программам в виде файлов псевдо файловая система proc
sysfs - информация об аппаратных устройствах, обнаруженных ядром операционной системы на шинах PCI, USB, SCSI и прочих,
предоставляет псевдо файловая система sysfs.
Пример программ которые используют псевдо файловые системы proc и sysfs:
uptime
ps
lsmod
lspci
lsusb
lsscsi
Проверка:
strace -fe open,openat uptime
cat /proc/uptime
cat /proc/loadavg
strace -fe open,openat lspci -nn
cat /sys/bus/pci/devices/0000:00:14.0/config
cat /sys/bus/pci/devices/0000:00:14.0/vendor
cat /sys/bus/pci/devices/0000:00:14.0/device
cat /sys/bus/pci/devices/0000:00:14.0/class
cat /sys/bus/pci/devices/0000:00:14.0/revision
Внеядерные файловые системы:
FUSE (Filesystem in userspace)
Это:
archivemount
sshfs
encfs
curlftpfs
fusermount
Прова доступа:
stat filename
id
chown
chgrp
usermod
базовые права:
read - 4
write - 2
execute - 1 (execve)
Пример как это работает:
stat 1
Access: (0644/-rw-r--r--)
chmod 421 1
stat 1
Access: (0421/-r---w---x)
chmod 777 1
stat 1
Access: (0777/-rwxrwxrwx)
Семантика режима доступа для разных типов файлов:
файлы = r - читать файл
w - изменять файл
x - исполнять файл
каталоги = w - это значит что из каталога можно стирать файлы из списка
r - право просмотра списка файлов имен файлов
x - право прохода в каталог
chmod ugo + rwx filename
chmod ugo - rwx filename
user
group owner
chmod a= filename защитить файл от записи
Дополнительные атрибуты файлов:
s - Set user/group ID (SUID Set User ID или Set Group ID) - атрибут не явного делегирования полномочий
Типичной задачей, требующей неявного делегирования полномочий, является проблема невозможности изменения пользователями своих учетных записей,
которые хранятся вдух файлах таблицах - passwd и shadow, доступных на чтение и запись только пользователем root,
однако пользователь может воспользоваться программой passwd для изменения своей учетной записи.
passwd
chfn
chsh
ping
traceroute
at
crontab
t - sTicky - липучка, атрибут ограниченного удаления
Служит для базового ограничения записи(w) в каталоге, но только своих файлов.
Например каталог tmp
Кому то этого было не достаточно и были придуманы еще ACL для файлов. POSIX.1e
ACL - access control lists
getfacl
setfacl
lsattr
chattr
a - append only (только добавление в файл)
i - immutalbe (не прикосаемый файл)
s - secure deletion
S - synchronous update
Прова по умолчанию
umask
Мандатные права пользователя:
DAC - (discretionary access control)
Модуль принудительного разграничения доступа AppArmor:
apparmor-utils
aa-status
Модуль принудительного разграничения доступа SELinux
SElinux (Security Enhanced Linux)
sestatus
Что ты такое модуль управления принудительного разграничения доступа Astra Linux
PARSEC - обеспечение безопасности информационных потоков
pdp-id
pdp-ls -M
Программы и библиотеки
Программа представляет собой алгоритм, записанный на определенном языке, понятном исполнителю программы.
Различают машинный язык. понятный центральному процессору, и языки более высоких уровней (алгоритмические), понятные
составителю программы - программисту.
Алгоритмы - некий набор инструкций, выполнение которых приводит к решению конкретной задачи.
Согласно hier, откомпилированные до машинного языка программы размещаются в каталогах:
/bin
/sbin
/usr/bin
/usr/sbin
/usr/local/bin
/usr/local/sbin
А библиотеки в каталогах
/lib
/usr/lib
/usr/local/lib
Программы имеют специальный запускаемый формат ELF executalbe
ldd (Loader dependencies)
(SONAME. shared object name)
file /usr/bin/ls
ldd /usr/bin/ls
Стоит заметить:
Файла библиотеки linux-vdso.so.1 (реализующий интерфейс системных вызовов к ядру) не существует,
так как он является виртуальной(VDSO, virtual dynamic shared object)
Для большинства библиотек зависимости устанавливаются с помощью SONAME вида libNAME.so.X
lib - стандартный префикс(library, библиотека)
.so - суффикс(shared object, разделяемый объект)
NAME - имя собственное
.X - номер версии ее интерфейса
ld.so
ldconfig
Библиотеки имеют специальный запускаемый формат ELF shared object
Не стоит забывать что самой главной программой является Ядро linux
uname -r
file /boot/vmlinuz
Модули ядра:
insmod
modprobe
rmmod
modinfo
lsmod
init_module
delete_module
/proc/modules
lspci -k
lsusb -t
Процессы и нити:
fork - системный вызов порождение нового процесса
COPY - создает копию родительского процесса
exit - уничтожение процесса и завершение процесса
SIGCHILD - сообщение родительскому(parent процессу о завершении дочернего (child)
status - статус завершения от дочернего процесса
wait - родительский процесс ждет завершения дочернего
zombie - состояние дочернего процесса если он вдруг стал сиротой
clone - универсальный вызов позволяющий при порождении процесса, задать и указать общие ресурсы процессов, указать частные ресурсы и т.д.
Примеры:
dd if=/dev/cdrom of=plan9.iso &
ps f
find /usr/share/doc -type f -name '*.html' | xargs -n1 wx -l | sort -k 1 -nr | head 1 &
ps fj
wait
ps f -C postgres
ssh server
ps -f -C sshd
ps f -C apache2
ps fo pid,nlwp,cmd -C apache2
ps -fLc rsyslog
ps -fLC systemd
ls -lh plan9.iso
time bzip plan9.iso &
ps f
ps -fLp 5546
fg
ls -lh plan9.iso.bz2
time pbzip2 -d plan9.iso.bz2
time pbzip2 plan9.iso &
ps f
ps -fLp 5572
fg
tar czf docs.tgz /usr/share/doc &
ps f
fg
strace -fe clone,clone3,fork,vfork,execve tar czf docs.tgz /usr/share/doc
pbzip2 plan9.iso &
strace -q -fe clone,clone3,fork,vfork,execve pbzip2 plan9.iso
Дерево процессов:
Процессы операционной системы принято классифицировать на системные (ядерные), демоны и прикладные, исходя из их назначения и свойств.
Прикладные процессы выполняют обычные пользовательские программы(man, ping, etc), для чего им выделяется индивидуальная память,
объём которой указан в столбце VSZ вывода команды ps. Такие процессы обычно интерактивно взаимодействуют с пользователем
посредством управляющего терминала(исключение графические программы), указанного в столбце TTY вывода программы ps.
Демоны, процессы класса демоны(daemons) выполняются системные программы, реализующие те или иные службы операционной системы.
Например: cron, sshd, rsyslogd, systemd-udevd. У них отсутствует управляющий терминал в столбце TTY вывода программы ps.
Зачастую демоны имеют суффикс d в конце названия.
Ядерные процессы, процессы ядра, выполняются параллельные части ядра операционной системы.
У них нету индивидуальной виртуальной памяти VSZ, ни управляющего терминала TTY в выводе программы ps.
Более того ядерные процессы не выполняют отдельную программу, загружаемую из ELF файла,
поэтому их имена COMMAND являются условными и изображаются в квадратных скобках,
и имеют особое состояние I в столбе STAT вывода программы ps.
Ядерные нити выполняются в общей памяти ОС.
ps faxu
ps -uaxf
pstree -cnAhT
Маркеры доступа:
Возможность процесса по отношению к объектам, доступ к которым разграничивается при помощи дискреционных механизмов,
определяются значение его атрибутов, формирующих его DAC-маркер доступа.
Атрибуты: RUID, RGID, EUID, EGID.
man 7 credentials
man -k credentials
id
ps fo euid,ruid,egid,rgid,user,group,tty,cmd
who
ls -la /etc/shadow /dev/tty2 /dev/tty3 /dev/pts/ptmx
ls -la /usr/bin/passwd /usr/bin/wall
ls -ln /usr/bin/passwd /usr/bin/wall
ps ft pts/1,pts/2 o pid,ruid,rgid,euid,egid,tty,cmd
Для selinux
id -Z
ps Zf
sesearch -T -t dhcpc_exec_t -c process
ls -Z /usr/sbin/dhclient
ps -ZC dhclient
cababilities
CAP_SYS_PTRACE - эта привилегия позволяет процессам трассировщикам strace и ltrace, использующих системный вызов ptrace, трассировать программы
CAP_SYS_NICE - привилегия позволяющая менять приоритет процесса (nice)
CAP_KILL - привилегия позволяет посылать сигналы процессам
CAP_FOWNER - привилегия позволяет процессам изменить режим доступа, мандатную ветку, флаги, атрибуты
CAP_LINUX_IMMUTABLE - управления флагами i (immutable) и a(append)
CAP_SETFCAP - устанавливать флаговые привилегии
CAP_NET_RAW - создание необработанных (raw) и пакетных (packet) сокетов
ps fo user,pid,cmd -C NetworkManager,postgres,apache2,systemd
getpcaps 1221
getcap /bin/ping
setcap cap_net_raw+ep /bin/ping
Пример как дать права для шарка:
tshark
strace -fe execve tshark
getcap /usr/bin/dumpcap
setcap cap_net_raw+ep /usr/bin/dumpcap
tshark -i eth0
Другие атребуты:
ps fe
ps fx
pwdx ID
pwdx 1235
Распределение процессора между процессами:
Переключением центрального процесса между задачами (процессами и нитями)
выполняет специальная компонента подсистемы управления процессами
называемая планировщиком (scheduler)
Именно планировщик определенным образом выбирает из множества неспящих, готовых к выполнению(runable) задач одну,
которую переводит в состояние выполнения (running).
Выбор задачи происходит естественным образом, когда текущая выполнявшиеся задача переходит в состояние сна(sleep)
Ещё существуют вытесняющие алгоритмы планирования, которые ограничивают непрерывное выполнения задач,
принудительно прерывают ее выполнение по исчерпании выданного ей кванта времени(timeslice) и
вытесняется она во множество готовых, после чего производит выбор новой задачи, подлежащей выполнению.
Для пользователей применяется алгоритм CFS(completely fair scheduler)
Согласно которому процессорное время распределяется между неспящими задачами справедливым (fair) образом.
Для двух задач с равным приоритетом должно быть выделено 50%.
приоритеты называется любезностью:) NICE
-20 ... +19
-20 сделать немедленно, сейчас же (выдается больше всего процессорного времени)
+19 делать неспеша
При отсутствии конкуренции за процессорное время, приоритет не будет играть никакой роли.
Инфа о cpu:
nproc
lsclpu
Пример управления приоритетом:
bzip2 --best -kf plan9.iso &
bzip2 --best -kf plan9.iso &
ps fo pid,pcpu,pri,ni,psr,cmd
renice +10 ID_process
renice +10 1234
ps fo pid,pcpu,pri,ni,psr,cmd
taskdet -p 3 1222
nice -n 5 time bzip2 --best -kf plan9.iso &
nice -n 15 time bzip2 --best -kf plan9.iso &
ps fo pid,pcpu,pri,ni,psr,cmd
wait
Другие планировщики:
FIFO (First in First out)- выполняет задачи пока не завершит
RR (Round Robin) - выполняет задачи по очереди чуть одна чуть другая PQ (Priority Queue)
EDF ( Earliest Deadline First) - Алгоритм гарантирует выполнение задачи и не позволяет ее вытеснить пока она выполняется.
Политики планирования:
SCHED_OTHER, SCHED_BATHC, SCHED_IDLE - CFS
SCHED_FIFO, SCHED_RR - FIFO, RR
SCHED_DEADLINE - EDF
taskset - позволяет привязать процесс к одному потоку процессора
chrt - смена алгоритма шедулера
Пример смены планировщика:
ps -f
chrt -b 0 time bzip2 --best -kf plan9.iso &
chrt -o 0 time bzip2 --best -kf plan9.iso &
chrt -i 0 time bzip2 --best -kf plan9.iso &
ps fo pid,pcpu,class,pri,ni,psr,cmd
ps -f
chrt -pr 99 ID_PROCESS
ps fo pid,psr,cls,ni.pri,pcpu,comm
chrt -r 1 taskset -c 2 bzip2 --best -kf plan9.iso &
chrt -r 1 taskset -c 2 bzip2 --best -kf plan9.iso &
ps fo pid,psr,cls,ni,ori,pcpu,comm
chrt -r 2 taskset -c 2 bzip2 --best -kf plan9.iso &
ps fo pid,psr,cls,ni.pri,pcpu,comm
top -b -n1 -p ID,ID,ID
top -b -n1 -p 123,321,555
Ввод и вывод
Планировщики ввода и вывода
SCAN, C-SCAN, LOOK, C-LOOK....
I/O scheduler
Сортировка(sorting)
Слияние(mergiring)
Планировщик deadline один из первых для работами с операциями ввода и вывода.
mq-dedline
CFQ
BFQ
kyber - современный
Посмотреть какой у вас планировщик для дисков:
cat /sys/block/{sda,sdb,sr0}/queue/scheduler
cat /sys/block/sda/queue/scheduler
Пример:
findmnt -T
cat /sys/block/sda/queue/scheduler
dd if=/dev/urandom of=big1 bs=16384 count=1024
dd if=/dev/urandom of=big2 bs=16384 count=1024
sync
dd if=big1 of=/dev/null iflag=direct &
dd if=big2 of=/dev/null iflag=direct &
wait
ionice -c best-effort -n 7 dd if=big1 of=/dev/null iflag=direct &
ionice -c best-effort -n 0 dd if=big1 of=/dev/null iflag=direct &
wait -n
wait -n
Память:
Управление памятью - механизм страничного отображения - MMU
MMU - (Memory Management Unit, Блок управления памятью)
Процессы работают с виртуальными адресами воображаемой памяти (virtual address),
отображаемым устройством MMU на физические адреса (physical address) настоящей оперативной памяти.
Для отображения оперативной памяти RAM(random access memory) условно разбивается на гранулы по 4Кбайт,
которые выделяются процессам.
Память процесса состоит из:
страниц (page)
специальных таблиц (page table)
сопоставленные выделенные страничные кадры (page frame)
ps fux
вывод в килобайтах
VSZ (virtual size) - суммарный объём всех страниц процесса (в том числе и выгруженных)
RSS (resident set size) - суммарный объём всех его страничных кадров в оперативной памяти, т.е. реальное потребление
системные вызовы mmap/munmap, mlock, mprotect, msync, madvise
COW - cppy-on-write - любые попытки изменения (write) приводят к созданию их копии(copy), куда попадают изминения
ps fux
pmap -d PID
pmap -d 775
pmap - покажет память процесса
ldd /usr/bin/hostname
strace hostname
top
для добавления столбика с SWAP нажмите "g 3" а после "f"
top -p $$
free -mw - статистика использования памяти
Пример:
dd if=/dev/urandom of=big bs=4069 count 262144
ld -lh big
free -mw
vi big
pd -f
free -mw
top -b -n1 -p enter_PID_vi
kill enter_PID_vi
free -mw
Механизмы сигналов
man signal
man -k signal
man kill
kill - команда отсылки сигналов
Ctrl + C - вызывает kill для выполняемой команды в консоли (SIGINT)
stty -a - покажет сигнал ^C и другие возможные сигналы в текущей консоли
Пример
dd if=/dev/zero of=/dev/null
Ctrl+c
^C
А если мы запустим это в фоне
dd if=/dev/zero of=/dev/null &
jobs
jobs -l
kill -SIGINT enter_PID_jobs
Но такой сигнал убьет процесс без сохранения данных на диск
А если хочется сохранить данные SIGQUIT №3
dd if=/dev/zero of=/dev/null &
jobs -l
kill -SIGQUIT enter_PID_jobs
^Quit
Для некоторых процессов и демонов не возможно послать сигнал ^C и ^ но возможно послать SIGTERM №15
dd if=/dev/zero of=/dev/null &
kill -SIGTERM enter_PID_jobs
Есть специальные сигналы для приостановки(№19 SIGSTOP) работы и возобновления(SIGCOUNT №18):
bzip2 big &
top -b -n1 -p enter_PID_bzip2
kill -SIGSTOP enter_PID_bzip2
ps -f
jobs -l
top -b -n1 -p enter_PID_bzip2
kill -SIGCOUNT enter_PID_bzip2
top -b -n1 -p enter_PID_bzip2
Самый наверно страшный сигнал №9 SIGKILL
Не желательно его использовать бездумно
Чаще всего приводит к созданию зомби
безусловное завершение процесса
Есть еще сигнал безусловной приостановке №19 SIGSTOP
kill -l покажит все возможные сигналы
dc - стековый калькулятор поможет преобразовывать из dec в hex и двоичный
dc -e 26i3o00484004p
Также процесс можно приостановить клавишами Ctrl+s
Возобновить Ctrl+q
bg - такой командой продолжить выполнение в фоне
fg - вытащить команду из фона
Межпроцессорное взаимодействие
IPC (iter-process communication)- средства межпроцессорного взаимодействия
Применяются каналы, сокеты, очереди сообщений и разделяемая память
Синхронизация действий процессов над совместно используемыми объектами - семафоры.
Неименованные каналы
Самый простой обмен между информацией между родственными процессами (родитель и любой потомок)
Два дескриптора:
первый передача (записи) в канал
второй прием (чтения) из канала
Пример:
strace -fe pipe,execve tar cjf /tmp/docs.tgz /usr/share/doc
^Z (Ctrl+z)
ps -f
lsof -p enter_PID_tar
Именованные каналы
Именованные каналы повторяют поведение неименованных каналов,
но предназначены для обмена информацией между неродственными процессами.
Именованные каналы используются крайне редко.
Пример:
ls -l /run/initctl /dev/initctl
lsof /run/initctl
Неименованные локальные сокеты
Именованные каналы = поставщик-> потребитель (односторонний обмен)
Сокет = клиент <-> сервер (двух сторонний обмен)
Сокет - устоявшиеся русская калька с англ. socket, буквально означающая "разъём", например,
220-вольтовые розетку и вилку, или сетевую розетку и вилку RJ-45, или 3.5гнездо для наушников и соответствующий штекер.
Пример:
strace -fe socketpair, execve rsync -a /usr/share/doc /tmp/a
ps f
lsof -p enter_PID_rsync
Именованные локальные сокеты
Наличие имени канала и сокета
Многие системные сервисы linux как раз используют именованные локальные сокеты.
Пример: systemd, x-windows-system, wayland, d-bus, wi-fi
Терминальные мультиплексоры screen и tmux
tty
screen
tty
Ctrl+A C
tty
ps fp enter_PID_screen t pts/1,pts/2
screen ls
screen -r
Разделяемая память, семафоры и очереди сообщений
ipcs
ipcs -m -p
dc -e enter_ipcs_string
ps up PID
pmap PID
fuser -v /var/cache/nscd/hosts
pmap PID
findmnt /dev/shm
fuser -v /dev/shm/*
ps p PID,PID,PID
pmsp -p PID
Семафоры и очереди сообщений
ipcs -q
ipcs -s
findmnt /dev/mqueue
ls -l /dev/mqueue
ls -l /dev/shm/sem.*
Программирование:
Интерпретаторы и их сценарии:
ash, dash, ksh, bash, zsh, fish
Языки:
perl, python, tcl
Универсальный комментарий в начале скрипта именованный shebang.
#!/bin/bash
#!/usr/bin/perl
#!/usr/bin/python
Примеры:
file /bin/fgrep
head -1 /bin/fgrep
file /bin/gunzip
head -1 /bin/gunzip
file /bin/lsb_release
head -1 /bin/lsb_release
file /usr/bin/mimetype
head -1 /usr/bin/mimetype
file /usr/bin/netwag
head -1 /usr/bin/netwag
printenv PATH
pwd
Встроенные и внешние команды
which -a cd
type -a cd
which -a pwd
type -a pwd
Перенаправление потоков ввода-вывода
0 - Стандартный ввод (stdin) — поток данных, который программа получает на вход (по умолчанию — клавиатура).
1 - Стандартный вывод (stdout) — поток, в который программа записывает результаты (по умолчанию — терминал).
2 - Стандартный поток ошибок (stderr) — поток, куда выводятся сообщения об ошибках (по умолчанию — терминал).
Перенаправление stdout:
Оператор > позволяет записать вывод команды в файл. Если файл существует, он будет перезаписан.
ls > output.txt
Оператор >> добавляет вывод в конец файла, не перезаписывая его.
echo "Hello" >> output.txt
Чтобы перенаправить поток ошибок в файл, используется 2>.
ls /nonexistent 2> errors.txt
2>> добавляет ошибки в конец файла:
ls /nonexistent 2>> errors.txt
Перенаправление stdout и stderr вместе
Можно объединить выводы стандартного вывода и ошибок в один файл с помощью &>.
ls /nonexistent &> all_output.txt
Также можно использовать > file 2>&1, где 2>&1 указывает, что stderr перенаправляется туда же, куда и stdout:
ls /nonexistent > all_output.txt 2>&1
Перенаправление ввода (stdin)
Оператор < позволяет передать данные в команду из файла.
wc -l < input.txt
Конвейеры (Pipelines)
Конвейер | позволяет направить вывод одной команды на вход другой.
ls / | grep "home"
Специальные случаи перенаправления
Удаление вывода — отправка вывода в "черную дыру" (файл /dev/null), где он просто исчезнет:
ls /nonexistent > /dev/null 2>&1
Перенаправление файловых дескрипторов:
В Bash файловые дескрипторы можно перенаправлять с помощью конструкции n>file (где n — номер потока).
Например, 3>file откроет дескриптор 3 для записи в файл file.
Heredoc (встраивание многострочного текста)
cat < output.txt 2> errors.txt
Чтение из файла и отправка результата в другой файл:
grep "pattern" < input.txt > output.txt
Игнорирование ошибок:
command 2> /dev/null
Запись вывода и ошибок в один файл:
command > output.txt 2>&1
Раздельная запись stdout и stderr:
command > output.txt 2> errors.txt
Отправка всех данных в «черную дыру»:
command > /dev/null 2>&1
Арифметические действия:
set -x
RADIUS=10
CIRCLE=`expr 2 * $RADIUS * 355 / 113`
set -x
let CIRCLE=2*RADIUS*355/113; echo $CIRCLE
CIRCLE=$((2 * RADIUS * 355/113))
Экранирование:
ls -l
file Рабочий стол
file "Рабочий стол"
file 'Рабочий стол'
find . -name *.gz
set -x
find . -name "*.gz"
" " - слабое игнорирование (не распространяется на метасимволы ` $ )
'' - сильное экранирование, экранирует любые символы
Список команд:
command1 ; command2 ; command3 ; command4 - простой синхронный
command1 & command2 & command3 & command4 - простой асинхронный
command1 && command2 && command3 && command4 - условный список команд И (следующая команда выполняется если предыдущая выполнилась успешно)
command1 || command2 || command3 || command4 - условный список ИЛИ (следующая команда выполняется если не выполнилась предыдущая)
Составные списки / test / условия
whict test
which [
type -a test
этот тест возвращает 0 если нет ошибок
test -f /etc/passwd
echo $?
этот тест возвращает 0 если нет ошибок
[ -w /etc/passwd ]
echo $?
проверяем блочное устройство сдром. если диска нет , открываем лоток
[ -b /dev/cdrom ] && eject /dev/cdrom
Составной список if
if [!] list; then list; [elif [!] list; then;] ... [else list;] fi
if test -b /dev/csrom; then eject /dev/cdrom; fi
if [[ "$some_variable" == "good input" ]]; then
echo "You got the right input."
elif [[ "$some_variable" == "ok input" ]]; then
echo "Close enough"
else
echo "No way Jose."
fi
! - нет/не
&& - и
|| - или
-lt - меньше, применяется в квадратных скобках []
-gt - больше, применяется в квадратных скобках []
[[ Двойные квадратные скобки ]] работают в целом так же, как и [одинарные квадратные скобки],
но имеют дополнительные возможности вроде лучшей поддержки регулярных выражений.
(( Двойные круглые скобки )) это конструкция, позволяющая осуществлять арифметические вычисления внутри Bash.
Пример:
if [[ "$name" == "Ryan" ]] && ! [[ "$time" -lt 2000 ]]; then
echo "Sleeping"
elif [[ "$day" == "New Year's Eve" ]] || [[ "$coffee_intake" -gt 9000 ]]; then
echo "Maybe awake"
else
echo "Probably sleeping"
fi
Порой вам встретятся двойные квадратные скобки, как в примере выше.
А порой они будут одинарными:
if [ "$age" -gt 30 ]; then
echo "What an oldy."
fi
Иногда могут быть и круглыми:
!!! обрати внимание на age, это переменная и оформлена без ${age}
if (( age > 30 )); then
echo "Hey, 30 is the new 20, right?"
fi
А может и не быть:
if is_upper "$1"; then
echo "Stop shouting at me."
fi
Что происходит на самом деле:
if ANY_COMMAND_YOU_WANT_AT_ALL; then
# ... stuff to do
fi
Пример 0, скрипта iftst_v1:
#! /bin/sh
# Пример iftst_v0
if test $# -ne 2; then
echo "Команде должно быть передано ровно два параметра!"
exit 1
else
echo "Параметр 1: $1. Параметр 2: $2"
fi
Пример for в файле:
for variable in list
do
commands
done
Пример for в командной строке:
for variable in list ; do commands ; done
Пример использования for в командной строке:
$ ls
filemgr.png terminal.png
$ for f in *.png ; do mv $f screenshot-$f ; done
$ ls
screenshot-filemgr.png screenshot-terminal.png
Пример:
for i in a b с; do echo $i; done
Пример:
#! /bin/sh
for i in a b c; do
echo $i
done
case
case word in [ [(] pattern1 [| pattern2]... ) list ;;]... esac
ключевые словами case, in, esac
признак окончания ветви ;;
#!/bin/bash
# Скрипт, который использует конструкцию case
# переменная, значение которой сравнивается с набором значений
num=2
case $num in
1)
echo "num = 1"
;;
2)
echo "num = 2"
;;
3)
echo "num = 3"
;;
esac
echo "Конец программы"
exit 0
#!/bin/bash
echo "Какой цвет вам нравится больше всего?"
echo "1 - синий"
echo "2 - Красный"
echo "3 - Желтый"
echo "4 - Зеленый"
echo "5 - оранжевый"
read color;
case $color in
1) echo "Синий - основной цвет.";;
2) echo "Красный - основной цвет.";;
3) echo "Желтый - основной цвет.";;
4) echo "Зеленый - вторичный цвет.";;
5) echo "Оранжевый - вторичный цвет.";;
*) echo "Этот цвет недоступен. Пожалуйста, выберите другой.";;
esac
#!/bin/bash
# Скрипт, который использует конструкцию case
# переменная, значение которой сравнивается с набором значений
num=2
case $num in
1|2|3)
echo "num равно или 1 или 2 или 3"
;;
4)
echo "num равно 4"
;;
*)
echo "Неизвестное значение"
;;
esac
echo "Конец программы"
exit 0
for / while / until
for name in [ words ...]; do list; done
и циклы с условием "ПОКА"
while [!] list; do list; done
и "ДО"
until [!] list do list; done
с ключевыми словами for, in, while, until, do, done
for node in $(seq 1 254); do ping -c 1 -W 1 192.168.1.$node; done
while ! ping -c1 -w1 8.8.8.8 ; do sleep 1; date; done
until ping -c1 -w1 8.8.8.8 ; do sleep 1; date; done
Инструментальные средства обработки текста
Базовые регулярные выражения
? - Любой символ
* - Любое количество любых символов (в том числе ни одного), но не *-файлы!
** - Любые файлы и каталоги, в том числе из всех подкаталогов (начиная с версии bash 4.0 — shopt -s globstar)
[abc] - Один из символов, указанных в скобках
[a-f] - Символ из указанного диапазона
[!abc] - Любые символы, кроме тех, что указаны в скобках
[^аЬс] - Аналогично предыдущему
~ - Сокращенное обозначение домашнего каталога
. - Текущий каталог
.. - Каталог на один уровень выше
echo ab{l,2,3} - Возврат abl аЬ2 аЬЗ
echo a{1..4} - Возврат al а2 аЗ а4
echo $[3*4] - Арифметические вычисления
`команда` - Замена команды результатом ее выполнения
$(команда) - Вариант, аналогичный предыдущему
echo $? - вернет с каким результатом завершилась предыдущая команда (0 - нет ошибок)
Команда "символ" - Отмена интерпретацию любых специальных символов, кроме $
Команда 'символ' - Похоже на предыдущий вариант, но с большими ограничениями (не допускает подстановки переменных)
? - любой одиночный символ в шаблоне
* - любое количество любых символов в шаблоне
. - любой одиночный символ в регулярном выражении
.* - любое количество любых символов в регулярном выражении
grep '^[^#]' /etc/wgetrc
grep [^0-9][0-9][0-9][^0-9] /etc/services
Сетевая подсистема:
lspci
lspci -ks 02:00.1
modinfo iwlwifi e1000
ifconfig -a
ip link show
ip addr show dev wlp2s0
lsmod
Просмотр статистики по соединениям IPv4:
netstat -4autpn
netstat -4atupn
ss -4atupn
ss -4atplnu
Назначение IP адреса:
ifconfig eno1 10.0.10.10 up
ifconfig eno1
ping -c 1 10.0.0.10
ipaddress add 172.16.16.172/16 dev eno1
ipaddress show dev eno1
ping -c1 172.16.16.172
Маршрутизация:
Добавление маршрута по умолчанию:
ip route add 0.0.0.0/0 via 10.0.0.1
Показать таблицу:
route -n
ip route show
Диагностика:
traceroute -m 50 bad.horse
Автоматическая настройка сети:
pgrep NetworkManager
lsof -w +E -p ID_NetworkManager -a -U
strace -fe connect nmcli general
Проводная сеть:
nmcli dev
nmcki dev show enp0s25
nmcli con
nmcli conn add type ethernet ifname enp0s25
nmcli conn
nmcli conn up ethernet-enp0s25
nmcli dev show enp0s25
ip a show dev enp0s25
ip route show
Беспроводная сеть:
nmcli dev wifi rescan
nmcli dev wifi list
nmcli con add type wifi ifname wlp2s0 ssid SSID_NAME
nmcli dev show wlp2s0
ip a show dev wlp2s0
nmcli --ask dev wifi connect SSID_NAME
nmcli conn show
WPA cli:
pgrep wpa_supplicant
lsof +E -p ID_Wpa_supplicant -a -U
strace -fe connect wpa_cli -i wlp2s0 status
wpa_cli -i wlp2s0 status
wpa_cli -i wlp2s0 scan
wpa_cli -i wlp2s0 scan_results
wpa_cli -i wlp2s0 list_networks
wpa_cli -i wlp2s0 add_network
wpa_cli -i wlp2s0 select_network 1
wpa_cli -i wlp2s0 list_networks
VPN:
nmcli con edit type vpn
Служба имен и DNS/mDNS-резолверы
Отображение имен
Name service switch configuration
/etc/nsswitch.conf
Соответствующие модули libnss_*.so.
Номера портов
/etc/services
libnss_db.so.2
Примеры:
grep hosts /etc/nsswitch.conf
grep services /etc/nsswitch.conf
find /lib/ -name 'libnss_*'
Файловые таблицы имен:
/etc/hosts
/etc/services
Примеры:
cat /etc/hosts
grep http /etc/services
getent hosts ubuntu
getent services 53/udp
Резолверы:
sytemd-resolved
cat /etc/resolv.conf
Примеры:
ss -4autpn sport = :53
getent hosts ya.ru
host ya.ru
host 8.8.8.8
resolvectl dns
ss -4autpn spot = :5353
avahi-browse -arcl
avahi-resolve --name h1.local
geten hosts h2.local
Сетевые службы ssh
Для удаленного доступа были программы rlogin, rsh, telnet, и данные передавались в открытом виде, не было шифрования.
Служба ssh предназначена для организации безопасного (secure) доступа к сеансу командного интерпретатора (shell) удаленных сетевых узлов.
SSH
Конфиденциальность (плюс целостность) передаваемых данных.
Обеспечивается при помощи симметрического шифрования с помощью общего сеансового ключа.
Аутентичность (подлинность) взаимодействующих сторон.
Сеансовый ключ устанавливается обеими взаимодействующими сторонами при помощи
асимметричного алгоритма открытого согласования ключей протокола Диффи-Хелмана.
MITM (man in the middle) - атака
Пример:
ssh user@namehost.local
ssh user@192.168.0.124
uname -a
whoami
tty
logout
ssh user@192.168.0.124 uptime
Входы без пароля
ssh-keygen
ssh-copy-id user@192.168.0.124
Копирование:
scp file_name user@192.168.0.124:
sftp user@192.168.0.124
rsync -avzr user@192.168.0.124:/home/user/file.txt .
sshfs
LDAP
https://pro-ldap.ru
Системные вызовы open, read, write, close
LDAP (Lightweight Directory Access Protocol)
DIT (Directory Information Tree)
LDAP состоит в использовании принципа ООП (объектно-ориентированного проектирования), согласно которому
индивидуальные записи каталога (entries) являются объектами, т.е. экземплярами классов (class),
в свою очередь описывающих обязательными (must) и возможные (may) атрибуты (свойства) объектов.
Так, класс для описания персональных данных (objectClass: person) требует,
что бы его конечный экземпляр обязательно содержит атрибут sn (surname, фамилия) и cn (common name),
и позволяет содержать атрибут telephoneNumber.
А класс для описания свойств учетных записей (ojectClass: posixAccaunt) требуют наличия атрибутов uid (user identifier),
что на деле является "именем" учетной записи, uidNumber,
gidNumber (UID и GID учетные записи) и homeDirectory (домашний каталог пользователя)
и позволяет (если нужно) содержать атрибуты, такие как userPassword и loginShell.
Надо заметить, что принадлежность объекта к тому или иному классу тоже является атрибутом с именем ojectClass,
принадлежащему классу с названием top.
Само дерево записей LDAP-каталога организуется универсальным образом.
В LDAP при построении дерева на любом уровне для различия (distinguish) сущностей (записей)
может быть произвольно любой из атрибутов любых объектов, названных выше, например uid.
Относительно отличимые имена RDN (realtive distignuished name)
состоящих из имен атребута, uid=testla или uid=enstein
Аналогично FQDN в системе DNS записываются справа налево.
Для разделения имен в DNS используется точка "."
www.google.com
Почти также делается в LDAP но для разделения сущностей используется запятая
objectClass: dcObject
dc (Domain commponent)
dc=www, dc=google, dc=com
ldapsearch -LL -H ldap://ldap.forums.com -x -b "" -s base
ldapsearch -LL -H ldap://ldap.forums.com -x -b "" -s base mamingContexts
-b "" - пустой фильтр
-s base - запрос адресуется только к этому имени (-s scope)
ldapsearch -LLL -H ldap://ldap.forumsys.com -x -b dc=example,dc=com -s sub dn
ldapsearch -LLL -H ldap://ldap.forumsys.com -x -b dc=example,dc=com objectClass=posixAccaunt dn
ldapserach -LL -H ldap://ldap.forumsys.com -x -b uid=tesla,dc=example,dc=com -s base
X-server и X-client - рисует окна
Как любая другая сетевых служба, оконная система X состоит из X-сервера и X-клиентов,
взаимодействующих между собой посредством "X протокола"
X-сервер
Основная задача которого заключается в управлении оборудованием графического вывода и ввода.
Под управлением X-сервером находится графические дисплеи (видеоадаптеры и подключенные к ним мониторы), устройства ввода и вывода.
Именно X-сервер принимает подключения от X-клиентов.
Смотрим:
pgrep -l Xorg
ps o pid,tty,cmd p PID_ID_process
lsof -p PID_ID_process -a /dev
lsof -p PID_ID_process -a -U
lsof -p PID_ID_process -a -i
xdpyinfo | grep -A 4 screen
X-клиенты и X-протоколы
X-клиенты всегда создают хотя бы одно окно
xdpyinfo
xrandr - поворот экрана
glxifo
xlsclients
xwininfo - список созданных окон
xprop
Xnest
Xephyr
Примеры:
xwininfo -tree -root | grep gnome-terminal
xwininfo id 0x2aaasdasda | grep Map
xwininfo id 0x2aaasdasda | egrep 'Map|Width|Height'
xprop -id 0x2a00001 | grep ^WM_
WM_NAME - текст заголовка отображаемых окон
WM_CLIETN_MACHINE - имя узла сетевого узла X-клиента
WM_COMMAND - отображает команду, при помощи которой был запущен клиент
xlsclients -l | grep -C 3 gnome-terminal
Взаимодействие X-клиентов и X-сервера происходит при помощи локальных или сетевых сокетов
в зависимости от их взаимного местоположения и согласно адресу подключения,
указываемому на стороне X-клиентов при помощи переменой окружения DISPLAY в host:number
В случае сетевого:
DISPLAY=ubuntu.local:0
DISPLAY=192.168.0.100
В случае локального:
DISPLAY=:0
Примеры:
Xnest :0
Xnest :listen tcp &
lsof -p 10950 -a -i
lsof -p 10950 -a -U
xeyes
DISPLAY=:1 strace -fe connect xeyes
DISPLAY=ubuntu.local:1 strace -fe connect xeyes
Оконные менеджеры:
Оконные менеджеры - позволяют манипулировать окнами.
Примеры оконных менеджеров:
twm - один из самых первых
olvm
mwm
IceWM
Настольные пользовательские окружения:
Манипулируют и рисуют и есть свои программы.
GNOME - gnome-session(менеджер сеансов) и gnome-shell(оконный менеджер в свою очередь запускает его dbus-launch)
KDE - startkde(сценарий), ksmserver(менеджер сеансов), kwin(оконный менеджер)
XFCE
LXDE
В современных версиях практически безальтернативно используется D-Bus для взаимодействия с окнами и между окнами.
Библиотеки интерфейсных элементов:
сам X-server умеет рисовать примитивы, точки круги и т.д.
для более сложных используются специальные библиотеки
widget
Xaw
Xview
Motif
Tk
Qt
Xrender
Xlib
Современные это Qt и Gtk, на основе их разрабатывают KDE и GNOME
Пример как посмотреть доступные библиотеки:
ldd $(which xeyes) | grep -i libX
ldd $(which mwm) | grep -i libXm
ldd $(which wish) | grep -i libtk
ldd $(which gnome-shell) | grep -i libgtk
ldd $(which kcacl) | grep -i libqt.gui
Wayland
замена X серверу
Контейнеры и виртуальные машины:
Чрутизация:
Самым древним средством изоляции, известным со времен классической ОС UNIX,
является системный вызов chroot, позволяющий назначить процессам корень дерева каталогов,
от которого вычисляются все абсолютные путевые имена.
Каждый процесс имеет атрибут cwd (current working directory) и атрибут rtd(root directory).
pgrep -l avahi-daemon
sudo lsof -p ID_avahi-daemon | grep rtd
Пример Чрутизации:
не правильно но показательно:
mkdir c-137
chroot c-137 sh
sudo chroot c-137 sh
sudo strace -fe chroot,chdir,execve chroot c-137 sh
более менее правильно:
mkdir c-137/bin
cp /bin/sh c-137/bin
sudo chroot c-137 sh
ldd /bin/sh
Пространства имен:
namespaces
ps up $$
ls -la /proc/$$/ns
ps o pid,netns,mntns,pidns,comm p $$
stat -L /proc/$$/ns/net
Пример создания контейнера в пространстве имен с использованием unshare:
ps o pid,netns,mntns,pidns,comm p $$
sudo unshare -mnp -f -R c-137 --mount-proc busybox sh
Контейнеризация: runnc и docker
Docker(software)
LXC
OpenVZ
OCI (Open Container Ininitiative)
Помогает взаимодействовать с контейнерами программа runc
Пример runc:
runc spec
ls config.json
sed -n '/root.*{/,/}/p' config.json
sudo debbootstrap --variant=minbase --include iproute2 jammy rootfs
Docker:
сайт docker.io - образы
docker image ls
ls -l /var/run/docker.sok
docker image pull ubuntu:23.04
docker run -ti --hostname c-123 ubuntu:23.04
docker attach c-123
Группы управления cgroups
Управление ресурсами контейнеров
Загрузка linux
Процесс загрузки абсолютно любой операционной системы начинается с той компоненты,
которая собственно операционной системой и является - с ядра.
Все остальное это дополнительные компоненты, и нужны по месту, десктоп, сервер, роутер и т.д.
Главной задачей загрузки является размещение ядра ос в оперативной памяти и передача ей управления.
Эти задачи выполняет загрузчик ОС, который принципе не является ее частью.
Чаще всего выступает частью аппаратной платформы на которой выполняется ОС.
Загрузчик сильно зависит от аппаратной платформы, также должен соответствовать спецификациям платформы,
таким как способы разделения носителей на разделы, собственное размещение на этих носителях,
порядок передачи ему управления при старте платформы и т.д.
Платформа персонального компьютера она же "IBM PC Compatible"
BIOS - набор базовых услуг
Согласно BIOS носитель должны содержать таблицу разделов определенного вида в своем первом блоке "boot sector",
так называемой загрузочной записи MBR, анализировала таблицу разделов, выбирала активный раздел,
считывала его PBR(он же VBR (volume boot record) и передавала ему управление.
Установленная на этот активный раздел ОС обычно размещала свой загрузчик и выполнялась дальнейшая загрузка.
С развитием платформы BIOS развился в EFI, позднее в UEFI.
А MRR развился "GUID Partition table"
Процедура загрузки теперь предполагает наличие наличие специального системного раздела ESP (EFI System Partition),
которая содержит файловую систему FAT (File Allocation Table),
на которой в виде текущей (current) передается управление по умолчанию.
При любом виде загрузке BIOS/UEFI, загрузчик получив управление умеет правильно считать в оперативную память ядро ОС и передать ему управление.
Самым популярным загрузчиком linux является GRUB.
efibootmgr -v
В современных linux каталог ESP смонтирован в /boot/efi
А файлы grub чаще всего в корневой файловой системе в каталоге /etc и файлах grub.cfg
Само ядро располагается в каталоге /boot
EFI - каталог
grub - каталог grub
initrd.img - архив модулей (микро версия операционной системы, busybox)
vmlinuz-linux - основной файл, ядро linux
Загрузчик загружает обе части, а затем передает управление.
lsinitramfs /boot/initrd.img-generic | grep.ko$ | wc -l
lsinitramfs /boot/initrd.img-generic | grep bin/
lsinitramfs - показ содержимого
mkinitramfs - запаковка
unmkinitramfs - распаковка
GRE-туннель (Generic Routing Encapsulation)
GRE (Generic Routing Encapsulation) — это протокол,
который позволяет инкапсулировать различные сетевые протоколы в IP-пакетах,
создавая туннель между двумя конечными точками.
Это позволяет передавать пакеты через общую сеть (например, через интернет) как если бы они находились в частной сети.
IPIP (IP-in-IP) — это ещё один протокол туннелирования,
который работает схоже с GRE, но он только инкапсулирует IP-пакеты в IP.
Это довольно простое решение для создания туннеля.
GREtap — это расширение GRE-туннеля, которое добавляет возможность работать с Ethernet-кадрами, а не только с IP-пакетами.
Это позволяет передавать кадры уровня канала передачи данных (L2), что полезно для создания виртуальных локальных сетей (VLAN).
VXLAN (Virtual Extensible LAN) — это протокол, предназначенный для создания туннелей уровня L2 поверх IP-сети.
Он использует UDP-порты (чаще всего 4789) для инкапсуляции Ethernet-кадров,
что позволяет строить виртуальные локальные сети через общедоступные сети.
GRE подходит для гибких решений, позволяя инкапсулировать различные протоколы.
IPIP проще и используется для передачи только IP-пакетов.
GREtap расширяет возможности GRE, добавляя поддержку канала L2.
VXLAN — это решение для построения виртуальных L2-сетей поверх IP
Настройка:
GRE-туннель
ip link add name gretunnel type gre local 10.0.0.1 remote 10.0.0.2
ip addr add 192.168.0.1/24 dev gretunnel
ip link set dev gretunnel up
IPIP-туннель
ip tunnel add ipiptunnel mode ipip local 10.0.0.1 remote 10.0.0.2
ip addr add 192.168.0.1/24 dev ipiptunnel
ip link set dev ipiptunnel up
GRE+Ethernet (GREtap)
ip link add name gretap tunnel local 10.0.0.1 remote 10.0.0.2 ttl 255
ip addr add 192.168.0.1/24 dev gretap
VXLAN
ip link add vxlan0 type vxlan id 42 dev eth0 remote 10.0.0.2 dstport 4789
ip addr add 192.168.0.1/24 dev vxlan0
ip link set dev vxlan0 up
Смена имени хоста (hostname)
sudo hostnamectl set-hostname <новое_имя_хоста>
Пример:
sudo hostnamectl set-hostname mypc
Если команды hostnamectl нет, можно отредактировать файл:
vim /etc/hostname
Редактирование файла hosts
vim /etc/hosts
Найдите строку с текущим именем хоста и замените его на новое.
Она должна выглядеть примерно так:
--------------
127.0.0.1 localhost
127.0.1.1 mypc
-------------
Перезагружаем систему
reboot
Если у вас ультелиты systemctl все таки есть то можно так:
systemctl restart systemd-hostnamed
Отключение передачи имени хоста через DHCP
Изменение настроек DHCP-клиента:
vim /etc/dhcp/dhclient.conf
---------------------------
send host-name "";
---------------------------
Обновление настроек NetworkManager (если используете):
vim /etc/NetworkManager/NetworkManager.conf
-------------------------------------------
[main]
dhcp=dhclient
[dhcp]
send-hostname=false
-------------------------------------------
Перезапустите службу NetworkManager:
systemctl restart NetworkManager
Использование sed для автоматического редактирования файлов:
0. Изменение имени хоста:
Вот как можно внести изменения в файлы /etc/hostname, /etc/hosts, /etc/dhcp/dhclient.conf, и /etc/NetworkManager/NetworkManager.conf:
NEW_HOSTNAME="mypc"
# Изменение имени хоста в /etc/hostname
sudo sed -i "s/.*/$NEW_HOSTNAME/" /etc/hostname
# Изменение имени хоста в /etc/hosts
sudo sed -i "s/^(127.0.1.1s*).*/1$NEW_HOSTNAME/" /etc/hosts
1. Отключение передачи имени хоста в DHCP
Для /etc/dhcp/dhclient.conf:
sudo sed -i "/^send host-name/ s|.*|send host-name "";|" /etc/dhcp/dhclient.conf
sudo grep -q "^send host-name" /etc/dhcp/dhclient.conf || echo 'send host-name "";' | sudo tee -a /etc/dhcp/dhclient.conf
Для /etc/NetworkManager/NetworkManager.conf:
Убедимся, что параметры dhcp=dhclient и send-hostname=false добавлены:
sudo sed -i "/^[main]/,/^[/ s/^dhcp=.*/dhcp=dhclient/" /etc/NetworkManager/NetworkManager.conf
sudo sed -i "/^[dhcp]/,/^[/ s/^send-hostname=.*/send-hostname=false/" /etc/NetworkManager/NetworkManager.conf
# Добавляем секции, если их нет
sudo grep -q "^[main]" /etc/NetworkManager/NetworkManager.conf || echo -e "n[main]ndhcp=dhclient" | sudo tee -a /etc/NetworkManager/NetworkManager.conf
sudo grep -q "^[dhcp]" /etc/NetworkManager/NetworkManager.conf || echo -e "n[dhcp]nsend-hostname=false" | sudo tee -a /etc/NetworkManager/NetworkManager.conf
2. После внесения изменений перезапустите службы:
sudo systemctl restart systemd-hostnamed
sudo systemctl restart networking
sudo systemctl restart NetworkManager
Скрипт на баше:
#!/bin/bash
# Убедимся, что скрипт запускается с правами root
if [[ $EUID -ne 0 ]]; then
echo "Этот скрипт необходимо запускать с правами root."
exit 1
fi
# Новое имя хоста
NEW_HOSTNAME="mypc"
# Файлы для редактирования
HOSTNAME_FILE="/etc/hostname"
HOSTS_FILE="/etc/hosts"
DHCLIENT_FILE="/etc/dhcp/dhclient.conf"
NETWORK_MANAGER_FILE="/etc/NetworkManager/NetworkManager.conf"
echo "1. Изменяем имя хоста..."
# Изменение имени хоста в /etc/hostname
sed -i "s/.*/$NEW_HOSTNAME/" "$HOSTNAME_FILE"
# Изменение имени хоста в /etc/hosts
sed -i "s/^(127.0.1.1s*).*/1$NEW_HOSTNAME/" "$HOSTS_FILE"
echo "2. Отключаем передачу имени хоста через DHCP..."
# Настройка /etc/dhcp/dhclient.conf
if grep -q "^send host-name" "$DHCLIENT_FILE"; then
sed -i "/^send host-name/ s|.*|send host-name "";|" "$DHCLIENT_FILE"
else
echo 'send host-name "";' >> "$DHCLIENT_FILE"
fi
# Настройка /etc/NetworkManager/NetworkManager.conf
if grep -q "^[main]" "$NETWORK_MANAGER_FILE"; then
sed -i "/^[main]/,/^[/ s/^dhcp=.*/dhcp=dhclient/" "$NETWORK_MANAGER_FILE"
else
echo -e "n[main]ndhcp=dhclient" >> "$NETWORK_MANAGER_FILE"
fi
if grep -q "^[dhcp]" "$NETWORK_MANAGER_FILE"; then
sed -i "/^[dhcp]/,/^[/ s/^send-hostname=.*/send-hostname=false/" "$NETWORK_MANAGER_FILE"
else
echo -e "n[dhcp]nsend-hostname=false" >> "$NETWORK_MANAGER_FILE"
fi
echo "3. Перезапускаем службы..."
# Перезапуск служб для применения изменений
systemctl restart systemd-hostnamed
systemctl restart networking
systemctl restart NetworkManager
echo "Изменения применены!"
echo "Проверка текущего имени хоста:"
hostnamectl
Проверка:
Убедитесь, что имя хоста изменилось:
hostnamectl
Проверьте файл /etc/hosts и /etc/hostname:
cat /etc/hosts
cat /etc/hostname
Проверка сетевого демона:
systemctl status networking
Слушаем трафик:
sudo tcpdump -i eth0 port 67 or port 68
net.core.somaxconn=65535
Задает максимальное кол-во соединений, которые могут ожидать обработки в очереди.
Важно для приложений.
net.core.netdev_max_blacklog=65536
Определяет максимальный размер очереди сетевых устройств обрабатывающих трафик
net.ipv4.tcp_fin_timeout=15
Время до ожидания завершения соединения (флаг fin)
net.ipv4.tcp_tw_reuse=1
Разрешаем использования сокетов TIME-WAIT для новых соединений.
По факту разрешает использования портов в статусе TIME-WAIT для новых соединений.
net.ipv4.tcp_tw_recycle=1
Активирует режим повторного использования портов в статусе TIME-WAIT.
net.ipv4.tcp_max_tw_buckets=65536
Увеличиваем кол-во сокетов time-wait
net.ipv4.tcp_window_scalling=1
Управляет масштабированием окна TCP. Увеличиваем размер TCP-окна если это возможно
Сегменты — разновидность коллекций,
которые могут расширяться для хранения дополнительных элементов; а это как раз то, что нужно!
Оказывается, в Go существует структура данных, в которую можно добавлять новые значения,
— она называется сегментом.
Как и массив, сегмент состоит из нескольких элементов, относящихся к одному типу.
В отличие от массивов, существуют функции, позволяющие добавлять новые элементы в конец сегмента.
Отличие сегмента от массива:
Фактически это уже знакомый синтаксис объявления массива, только без указания размера.
var myArray [5]int // Массив — обратите внимание на размер.
var mySlice []int // Сегмент — размер не задан
В отличие от переменных для массивов, объявление переменной для сегмента не приводит к автоматическому созданию сегмента.
Для этого следует вызвать встроенную функцию make.
Функции передается тип создаваемого сегмента (он должен соответствовать типу переменной,
которой вы собираетесь присвоить сегмент)
и длина сегмента при создании.
Пример:
var notes []string
notes = make([]string, 7)
notes[0] = "do"
notes[1] = "re"
notes[2] = "mi"
fmt.Println(notes[2])
fmt.Println(notes[0])
Пример:
pr := make([]int, 5)
pr[0] = 99
pr[4] = 200
fmt.Println("pr[4] - pr[0] = ", pr[4]-pr[0])
Встроенная функция len для сегментов работает так же, как и для массивов.
Передайте len сегмент, и функция вернет его длину в виде целого числа.
Пример:
notes := make([]string, 7)
primers := make([]int, 5)
fmt.Println(len(notes))
fmt.Println(len(primers))
Циклы "for" и "for...range" работают с сегментами точно так же, как и с массивами:
Пример:
letters := []string{"a", "b", "c"}
for i := 0; i < len(letters); i++ {
fmt.Println(letters[i])
}
fmt.Println(" ")
for _, letter := range letters {
fmt.Println(letter)
}
Литералы сегментов
Как и с массивами, если вы заранее знаете, какими значениями должен быть заполнен сегмент в исходном
состоянии, то можете инициализировать сегмент этими значениями при помощи литерала сегмента.
Литерал сегмента очень похож на литерал массива, но если литерал массива содержит длину массива в квадратных скобках,
у литерала сегмента квадратные скобки пусты.
За пустыми скобками следует тип элементов, которые будут храниться в сегменте, и список исходных значений всех элементов, заключенный в фигурные скобки.
Вызывать функцию make необязательно, при использовании литерала сегмента ваш код создаст сегмент и заполнит его.
Сегмент:
[]int{9, 18, 27}
| | |
| | Список значений, разделенных запятыми.
| Тип элементов в сегменте
Пустая пара квадратных скобок
Пример:
notes := []string{"do", "re", "mi", "fa", "so", "la", "ti"} //Значения присваиваются с помощью литерала сегмента.
fmt.Println(notes[3], notes[6], notes[0])
primes := []int{ // Многострочный литерал сегмента.
2,
3,
5,
}
fmt.Println(primes[0], primes[1], primes[2])
Погодите!
Похоже, что сегменты могут делать все, что делают массивы, и в них можно добавлять элементы.
Тогда почему бы не ограничиться сегментами и не забыть про эту ерунду с массивами?
!!! Потому что сегменты построены на основе массивов.
!!! И вы не сможете понять, как работают сегменты, не понимая массивы.
Каждый массив существует на основе базового массива.
Данные сегмента на самом деле хранятся в базовом массиве,
а сегмент всего лишь предоставляет «окно» для работы с некоторыми (или всеми) элементами массива.
Когда вы используете функцию make или литерал сегмента для создания сегмента,
базовый массив при этом создается автоматически (и вы не можете обратиться к нему иначе как через сегмент).
Но вы также можете создать массив самостоятельно, а затем создать сегмент на основе этого массива при помощи оператора сегмента.
Пример:
underlyingArray := [5]string{"a", "b", "c", "d", "e"}
slice1 := underlyingArray[0:3]
fmt.Println(slice1)
Пример:
underlyingArray := [5]string{"a", "b", "c", "d", "e"}
i, j := 1, 4
slice2 := underlyingArray[i:j]
fmt.Println(slice2)
У оператора сегмента предусмотрены значения по умолчанию как для начального, так и для конечного индексов.
Если начальный индекс не указан, будет использовано значение 0 позиции.
Пример:
underlyingArray := [5]string{"a", "b", "c", "d", "e"}
slice4 := underlyingArray[:3]
fmt.Println(slice4)
А если не указан конечный индекс, то в сегмент включаются элементы от начального индекса и до конца базового завершается.
Пример:
underlyingArray := [5]string{"a", "b", "c", "d", "e"}
slice5 := underlyingArray[1:]
fmt.Println(slice5)
Базовые массивы
Как упоминалось ранее, сам сегмент не содержит данных,
это всего лишь «окно» для просмотра элементов базового массива.
Сегмент можно представить себе как микроскоп,
направленный на определенную часть предметного стекла (базовый массив).
Когда вы берете сегмент базового массива, то «видите» только ту часть элементов массива,
которая видна через этот сегмент.
Несколько сегментов могут существовать на основе одного базового массива.
В этом случае каждый сегмент становится «окном» для отдельного подмножества элементов массива.
Сегменты даже могут перекрываться!
Присваивание нового значения элементу сегмента приводит
к изменению соответствующего элемента в базовом массиве.
Если на один и тот же базовый массив указывают несколько сегментов,
то и изменения элементов массива будут видны во всех сегментах.
Из-за этих потенциальных проблем обычно рекомендуется создавать сегменты с использованием make или литерала
сегмента (вместо того, чтобы создать массив и применять к нему оператор сегмента).
С make и литералами сегментов вам никогда не приходится иметь дела с базовым массивом.
Расширение сегментов функцией «append»
В Go существует встроенная функция append, которая получает сегмент и одно или несколько значений,
которые присоединяются в конец сегмента.
Функция возвращает но вый, расширенный сегмент со всеми элементами исходного сегмента и новыми элементами,
добавленными в его конец.
Пример:
slice := []string{"a", "b"}
fmt.Println(slice, len(slice))
slice = append(slice, "c")
fmt.Println(slice, len(slice))
slice = append(slice, "d", "e")
fmt.Println(slice, len(slice))
Вам не нужно следить за тем, по какому индексу присваиваются новые значения, или за чем-нибудь еще!
Просто вызовите функцию append и передайте ей сегмент со значениями, которые добавляются в конец сегмента,
и вы получите новый расширенный сегмент.
Да, так просто!
Обратите внимание: возвращаемое значение append во всех случаях присваивается той же переменной сегмента,
которая передается append.
Таким образом предотвращается возможность непоследовательного поведения сегментов, возвращаемых append.
Базовый массив сегмента не может увеличиваться в размерах.
Если в массиве не остается места для добавления элементов, все элементы копируются в новый, больший массив,
а сегмент обновляется, чтобы он базировался на новом массиве.
Но поскольку все это происходит где-то за кулисами внутри функции append,
невозможно простым способом определить, имеет ли возвращенный сегмент тот же базовый массив,
как и переданный сегмент, или другой.
Если в программе будут оставаться оба сегмента, это может привести к непредсказуемому поведению.
Пример:
s1 := []string{"s1", "s1"}
s2 := append(s1, "s2", "s2")
s3 := append(s2, "s3", "s3")
s4 := append(s3, "s4", "s4")
fmt.Println(s1, s2, s3, s4)
s4[0] = "XX"
fmt.Println(s1, s2, s3, s4)
По этой причине при вызове append возвращаемое значение обычно присваивается той же переменной сегмента,
которая была передана append.
Если в программе хранится только один сегмент, то вам не придется беспокоиться о том,
используют ли два сегмента один базовый массив!
Пример:
s1 := []string{"s1", "s1"}
s1 = append(s1, "s2", "s2")
s1 = append(s1, "s3", "s3")
s1 = append(s1, "s4", "s4")
fmt.Println(s1)
Сегменты и нулевые значения
Как и в случае с массивами, при обращении к элементу сегмента,
которому не было присвоено значение, вы получите нулевое значение для этого типа.
Пример:
floatSlice := make([]float64, 10)
boolSlice := make([]bool, 10)
fmt.Println(floatSlice[9], boolSlice[5])
Пример:
var intSlice []int
var stringSlice []string
fmt.Printf("intSlice: %#v, stringSlice: %#vn", intSlice, stringSlice)
Ранее мы использовали пакеты os и bufio стандартной библиотеки для чтения данных по строкам с клавиатуры.
Те же пакеты могут использоваться и для построчного чтения данных из текстовых файлов.
В своем любимом текстовом редакторе создайте новый файл с именем data.txt.
Запишите в файле три наших значения с плавающей точкой, по одному числу в строке.
cat > data.txt << "EOF"
71.8
56.2
89.5
EOF
Пример программы:
package main
import (
"bufio"
"fmt"
"log"
"os"
)
func main() {
file, err := os.Open("data.txt") //Файл данных открыва
if err != nil {
log.Fatal(err)
}
scanner := bufio.NewScanner(file)
//Цикл выполняется до того, как будет достигнут конец файла, а scanner.Scan вернет false
for scanner.Scan() { //Читает строку из файла
fmt.Println(scanner.Text()) //Выводит строку
}
// Если при закрытии файла произошла ошибка то сообщить о ней и завершить работу
err = file.Close() //Закрывает файл для освобождения ресурсов.
if err != nil {
log.Fatal(err)
}
if scanner.Err() != nil {
log.Fatal(scanner.Err())
}
}
Наша тестовая программа readfile.go успешно читает данные из файла data.txt и выводит их.
А теперь разберемся, как же она работает.
Сначала строка с именем открываемого файла передается функции os.Open.
Эта функция возвращает два значения: указатель os.File, представляющий открытый файл, и значение ошибки.
Как и в случае с другими функциями, если значение ошибки равно nil, это означает,
что файл был открыт успешно, но любое другое значение указывает на то,
что произошла ошибка (например, если файл отсутствует или не читается).
В таком случае программа выводит сообщение об ошибке и завершается.
Чтение текстового файла в массив
Пример кода:
// Пакет datafile предназначен для чтения данных из файлов.
//package datafile
package main
import (
"fmt"
"bufio"
"os"
"strconv"
)
// GetFloats читает значение float64 из каждой строки файла. ошибку.
func GetFloats(fileName string) ([3]float64, error) {
var numbers [3]float64 // Объявление возвращаемого массива.
file, err := os.Open(fileName) //Открывает файл с переданным именем.
if err != nil {
return numbers, err
}
i := 0 //Переменная для хранения индекса, по которому должно выполняться присваивание
scanner := bufio.NewScanner(file)
for scanner.Scan() {
numbers[i], err = strconv.ParseFloat(scanner.Text(), 64)
if err != nil {
return numbers, err
}
i++ //Переход к следующему индексу массива.
}
err = file.Close()
if err != nil {
return numbers, err
}
if scanner.Err() != nil {
return numbers, scanner.Err()
}
return numbers, nil //Если выполнение дошло до этой точки, значит, ошибок не было, поэтому программа возвращает массив чисел и значение ошибки «nil ».
}
func main() {
fileName := "data.txt"
fmt.Println("Hello readfile")
fmt.Println(GetFloats(fileName))
}
Чтение файла и выполнение программы average. Еще один пример:
//average вычисляет среднее значение
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"log"
)
// GetFloats читает значение float64 из каждой строки файла. ошибку.
func GetFloats(fileName string) ([3]float64, error) {
var numbers [3]float64 // Объявление возвращаемого массива.
file, err := os.Open(fileName) //Открывает файл с переданным именем.
if err != nil {
return numbers, err
}
i := 0 //Переменная для хранения индекса, по которому должно выполняться присваивание
scanner := bufio.NewScanner(file)
for scanner.Scan() {
numbers[i], err = strconv.ParseFloat(scanner.Text(), 64)
if err != nil {
return numbers, err
}
i++ //Переход к следующему индексу массива.
}
err = file.Close()
if err != nil {
return numbers, err
}
if scanner.Err() != nil {
return numbers, scanner.Err()
}
return numbers, nil //Если выполнение дошло до этой точки, значит, ошибок не было, поэтому программа возвращает массив чисел и значение ошибки «nil».
}
func main() {
filename := "data.txt"
numbers, err := GetFloats(filename)
if err != nil {
log.Fatal(err)
}
var sum float64 = 0
for _, number := range numbers {
sum += number
}
sampleCount := float64(len(numbers))
fmt.Printf("Average: %0.2fn", sum/sampleCount)
}
Наша программа может обрабатывать только три значения!
cat > data1.txt << "EOF"
71.8
56.2
89.5
99.3
EOF
Пример ошибки:
panic: runtime error: index out of range [3] with length 3
goroutine 1 [running]:
main.GetFloats(0xd5676, 0x9, 0x0, 0x0, 0x0, 0x4d458, 0x162060)
/home/pi/githabmegafolder/c-test/02_lesson_golang/25_file/02_averange.go:25 +0x2e4
main.main()
/home/pi/githabmegafolder/c-test/02_lesson_golang/25_file/02_averange.go:46 +0x34
exit status 2
Введите команду "go doc", чтобы вывести документацию по любому пакету или функции.
Чтобы вывести документацию по пакету, передайте его путь импорта команде "go doc".
Например, информация о пакете "strconv" выводится командой "go doc strconv".
go doc -h
go doc -u http
go doc strconv
go doc strconv ParseFloat
go doc github.com/headfirstgo/keyboard
Команда go doc старается получить полезную информацию на основании анализа кода.
Имена пакетов и пути импорта включаются автоматически, как и имена функций, параметры и возвращаемые типы.
И все же команда go doc не умеет творить чудеса.
Если вы хотите, чтобы пользователи смогли узнать из документации о предназначении пакета или функции,
придется добавить эту информацию самостоятельно.
К счастью, это делается просто: нужно добавить в код документирующие комментарии.
Обычные комментарии Go, размещенные непосредственно перед директивой package или объявлением функции,
считаются документирующими комментариями и включаются в вывод go doc.
При добавлении документирующих комментариев следует соблюдать ряд правил:
- Комментарии должны состоять из полноценных предложений.
- Комментарии для пакетов должны начинаться со слова "Package", за которым следует имя пакета:
// Package mypackage enables widget management.
- Комментарии для функций должны начинаться с имени функции, которую они описывают:
// MyFunction converts widgets to gizmos.
- В комментарии также можно включать примеры кода, которые должны снабжаться отступами.
- Не включайте дополнительные символы для выразительности или форматирования (кроме отступов в примерах кода).
Документирующие комментарии будут выводиться в виде простого текста и должны форматироваться соответствующим образом.
go help
go help gopath
go help list
Многие программы работают со списками.
Списки адресов.
Списки телефонных номеров.
Списки товаров.
Массив представляет собой набор значений, относящихся к одному типу.
Представьте себе таблетницу — вы можете класть и доставать таблетки в любое отделение,
но при этом ее удобно переносить как единое целое.
Значения, хранящиеся в массиве, называются элементами.
Вы можете создать массив строк, массив логических значений или массив любого другого типа Go (даже массив массивов).
Весь массив можно сохранить в одной переменной, а затем обратиться к любому нужному элементу.
В массивах хранятся наборы значений.
Массив содержит заранее заданное количество элементов, а его размер не может увеличиваться или уменьшаться.
Чтобы объявить переменную для хранения массива, следует указать количество хранящихся в нем элементов в квадратных скобках ([]),
а затем тип элементов в массиве.
Чтобы присвоить значения элементам массива или прочитать их позднее, необходимо каким-то образом указать, какой элемент вам нужен.
Элементы в массиве нумеруются, начиная с 0.
Номер массива называется его индексом.
Пример массив нот:
var notes [7]string
notes[0] = "do"
notes[1] = "re"
notes[2] = "mi"
fmt.Println(notes[0])
fmt.Println(notes[1])
Массив целых чисел:
var primes [5]int
primes[0] = 2
primes[1] = 3
fmt.Println(primes[0])
Массив значений time.Time:
var dates [3]time.Time
dates[0] = time.Unix(1257894000, 0)
dates[1] = time.Unix(1447920000, 0)
dates[2] = time.Unix(1508632200, 0)
fmt.Println(dates[1])
Нулевые значения в массивах
Как и в случае с переменными,
при создании массивов все содержащиеся в них значения инициализируются нулевым значением для типа,
содержащегося в массиве.
Так массив значений int по умолчанию заполняется нулями.
С другой стороны, нулевым значением для строк является пустая строка,
так что массив строковых значений по умолчанию заполняется пустыми строками.
Нулевые значения позволяют безопасно выполнять операции с элементами массивов, даже если им не были присвоены значения.
Например, в следующем массиве хранятся целочисленные счетчики.
Любой элемент можно увеличить на 1 даже без предварительного присваивания значения,
потому что мы знаем, что все значения счетчиков начинаются с 0.
var counters [3]int
counters[0]++ // Первый элемент увеличивается с 0 до 1.
counters[0]++ // Первый элемент увеличивается с 1 до 2.
counters[2]++ // Третий элемент увеличивается с 0 до 1.
fmt.Println(counters[0], counters[1], counters[2])
Вывод:
2 0 1
При создании массива все содержащиеся
в нем элементы инициализируются нулевым
значением для типа, хранящегося в массиве.
Литералы массивов
Если вам заранее известны значения, которые должны храниться в массиве,
вы можете инициализировать массив этими значениями в форме литерала массива.
Литерал массива начинается как тип массива — с количества элементов в квадратных скобках,
за которым следует тип элементов.
Далее в фигурных скобках идет список исходных значений элементов массива.
Значения элементов должны разделяться запятыми.
[3]int{9, 18, 27}
| | |
| | Список значений, разделенных запятыми.
| Тип элементов в массиве.
|
Количество элементов в массиве.
var notes [7]string = [7]string{"do", "re", "mi", "fa", "so", "la", "ti"}
fmt.Println(notes[3], notes[6], notes[0])
var primes [5]int = [5]int{2, 3, 5, 7, 11}
fmt.Println(primes[0], primes[2], primes[4])
Литералы массивов также позволяют использовать короткие объявления переменных с помощью :=.
Короткое объявление переменной.
notes := [7]string{"do", "re", "mi", "fa", "so", "la", "ti"}
primes := [5]int{2, 3, 5, 7, 11}
Литералы массивов могут распространяться на несколько строк, но перед каждым переносом строки в коде должна стоять запятая.
Запятая даже должна стоять после последнего элемента в литерале массива, если за ним следует перенос строки.
(На первый взгляд этот синтаксис выглядит неуклюже, но он упрощает последующее добавление новых элементов в коде.)
text := [3]string{ // Все это один массив.
"This is a series of long strings",
"which would be awkward to place",
"together on a single line", // Запятая в конце обязательна.
}
Когда вы занимаетесь отладкой кода, вам не нужно передавать элементы массивов Println
и другим функциям пакета fmt один за одним.
Просто передайте весь массив.
Пакет fmt содержит логику форматирования и вывода массивов.
(Пакет fmt также умеет работать с сегментами, картами и другими структурами данных, которые будут описаны позднее.)
var notes [3]string = [3]string{"do", "re", "mi"}
var primes [5]int = [5]int{2, 3, 5, 7, 11}
fmt.Println(notes)
fmt.Println(primes)
Возможно, вы также помните глагол "%#v", используемый функциями Printf и Sprintf, — он форматирует значения так, как они отображаются в коде Go.
При форматировании с "%#v" массивы отображаются в форме литералов массивов Go.
fmt.Printf("%#vn", notes)
fmt.Printf("%#vn", primes)
Обращение к элементам массива в цикле
Вы не обязаны явно записывать целочисленные индексы элементов массивов, к которым обращаетесь в своем коде.
В качестве индекса также можно использовать значение целочисленной переменной.
notes := [7]string{"do", "re", "mi", "fa", "so", "la", "ti"}
index := 1
fmt.Println(index, notes[index]) // Выводит элемент массива с индексом 1.
index = 3
fmt.Println(index, notes[index]) // Выводит элемент массива с индексом 3.
for i := 0; i <= 2; i++ {
fmt.Println(i, notes[i])
}
При обращении к элементам массивов через переменную необходимо действовать внимательно и следить за тем,
какие значения индексов используются в программе.
Как упоминалось ранее, массивы содержат конкретное число элементов.
Попытка обратиться к индексу за пределами массива приводит к панике — ошибке,
происходящей во время выполнения программы (а не на стадии компиляции).
Проверка длины массива функцией «len»
Написание циклов, которые ограничиваются только правильными индексами, сопряжено с определенным риском ошибок.
К счастью, есть пара приемов, которые упрощают этот процесс.
Во-первых, вы можете проверить фактическое количество элементов в массиве перед обращением к элементу.
Для этого можно воспользоваться встроенной функцией len, которая возвращает длину массива (количество содержащихся в нем элементов).
notes := [7]string{"do", "re", "mi", "fa", "so", "la", "ti"}
for i := 0; i < len(notes); i++ {
fmt.Println(i, notes[i])
}
Впрочем, и здесь существует некоторый риск ошибок.
Хотя len(notes) возвращает наибольший индекс, к которому вы можете обращаться,
равен 6 (потому что индексирование массивов начинается с 0, а не с 1).
При попытке обратиться по индексу 7 возникнет ситуация паники.
Безопасный перебор массивов в цикле «for…range»
В другом, еще более безопасном способе обработки всех элементов массива используется специальный цикл for...range.
В форме с range указывается переменная для хранения целочисленного индекса каждого элемента,
другая переменная для хранения значения самого элемента и перебираемый массив.
Цикл выполняется по одному разу для каждого элемента в массиве;
индекс элемента присваивается первой переменной, а значение элемента — второй переменной.
В блок цикла включается код для обработки этих значений.
for index, value := range myArray {
// Блок цикла.
}
Эта форма цикла for не содержит запутанных выражений инициализации, условия и завершения.
А поскольку значение элемента автоматически присваивается переменной, риск обращения к недействительному индексу массива исключен.
Форма цикла for с range читается безопаснее и проще, поэтому именно она чаще всего встречается при работе с массивами и другими коллекциями.
notes := [7]string{"do", "re", "mi", "fa", "so", "la", "ti"}
for index, note := range notes {
fmt.Println(index, note)
}
Цикл выполняется семь раз, по одному разу для каждого элемента в массиве notes.
Для каждого элемента переменной index присваивается индекс элемента,
а переменной note присваивается значение элемента. После этого мы выводим индекс и значение.
Помните, как при вызове функции с несколькими возвращаемыми значениями мы хотели проигнорировать одно из них?
Это значение присваивалось пустому идентификатору ( _ ),
чтобы компилятор Go просто отбросил это значение без выдачи сообщения об ошибке...
То же самое можно проделать со значениями из циклов "for...range".
Если вам не нужен индекс каждого элемента массива, присвойте его пустому идентификатору:
notes := [7]string{"do", "re", "mi", "fa", "so", "la", "ti"}
for index, note := range notes {
fmt.Println(index, note)
}
А если вам не нужна переменная для значения, замените ее пустым идентификатором
Оператор & (амперсанд) используется в Go для получения адреса переменной.
Например, следующий код инициализирует переменную, сначала выводит ее значение, а затем адрес переменной...
Пример кода:
package main
import "fmt"
func main() {
amount := 6
fmt.Println(amount) //Выводит значение переменной
fmt.Println(&amount) //Выводит адрес переменной
}
вывод кода:
6 //Значение переменной.
0x400011c010 //Адрес переменной.
Адрес можно получить для переменной любого типа.
Обратите внимание, все переменные имеют разные адреса.
Еще пример кода:
package main
import "fmt"
func main() {
var myInt int
fmt.Println(&myInt)
var myFloat float64
fmt.Println(&myFloat)
var myBool bool
fmt.Println(&myBool)
}
Вывод кода:
0x40000ba010
0x40000ba018
0x40000ba030
И что же собой представляют эти «адреса»?
Чтобы найти конкретный дом в плотно застроенном городе, вам нужно знать его адрес...
Память, выделяемая компьютером программе, так же переполнена, как и городские улицы.
Она забита значениями переменных: логическими значениями, целыми числами, строками и т. д.
Зная адрес переменной, вы сможете воспользоваться им для получения значения, хранящегося в переменной.
Адрес
|
0x1040a100 0x1040a108 0x1040a110 0x1040a118 0x1040a120 0x1040a128
true 6 ... ... ... 3.1415
|
значение, хранящееся по этому адресу!
!!! Значения, представляющие адреса переменных, называются указателями, потому что они указывают на область памяти, в которой хранится переменная.
Типы указателей
Тип указателя состоит из знака * и типа переменной, на которую ссылается указатель.
Например, тип указателя на переменную int записывается в виде *int (читается «указатель на int»).
С помощью функции reflect.TypeOf можно вывести типы указателей из приведенной ранее программы:
package main
import (
"fmt"
"reflect"
)
func main() {
var myInt int
fmt.Println(reflect.TypeOf(&myInt)) //Получает указатель на myInt и выводит тип указателя.
var myFloat float64
fmt.Println(reflect.TypeOf(&myFloat)) //Получает указатель на myFloat и выводит тип указателя.
var myBool bool
fmt.Println(reflect.TypeOf(&myBool)) //Получает указатель на myBool и выводит тип указателя.*
}
В программе можно объявлять переменные, содержащие указатели.
В таких переменных могут храниться только указатели на один конкретный тип переменной,
так что переменная может содержать только указатели *int, только указатели *float64 и т. д.
package main
import "fmt"
func main() {
myInt := 4 //Значение
myIntPointer := &myInt //Указатель
fmt.Println(myIntPointer) //Выводится сам указатель.
fmt.Println(*myIntPointer) //Выводится значение, на которое ссылается указатель.
myFloat := 98.6 //Значение
myFloatPointer := &myFloat //Указатель
fmt.Println(myFloatPointer) //Выводит сам указатель
fmt.Println(*myFloatPointer) //Выводится значение, на которое ссылается указатель.
myBool := true //Значение
myBoolPointer := &myBool ////Указатель
fmt.Println(myBoolPointer) //Выводит сам указатель
fmt.Println(*myBoolPointer) //Выводится значение, на которое ссылается указатель.
Как и с другими типами, при немедленном присваивании исходного значения переменной-указателю можно воспользоваться коротким объявлением переменной.
package main
import "fmt"
func main() {
var myBool bool
myBoolPointer := &myBool //Короткое объявление переменной-указателя.
fmt.Println(myBoolPointer)
}
Чтение или изменение значения по указателю
!!! Оператор * может использоваться для обновления значения по указателю.
package main
import "fmt"
func main() {
myInt := 4 //Значение
fmt.Println(myInt) //Вывести значение
myIntPointer := &myInt //Создаем указатель
*myIntPointer = 8 //Новое значение присваивается переменной, на которую ссылается указатель (myInt).
fmt.Println(*myIntPointer) //Выводится значение переменной, на которую ссылается указатель.
fmt.Println(myInt) //Значение переменной выводится напрямую.
}
/*
4 Исходное значение myInt.
8 Результат обновления *myIntPointer.
8 Обновление значения myInt (то же, что *myIntPointer).
*/
В приведенном коде команда *myIntPointer = 8 обращается к переменной,
на которую ссылается указатель myIntPointer (то есть переменной myInt) и присваивает ей новое значение.
Таким образом, обновляется не только значение *myIntPointer, но и myInt
Использование указателей с функциями
Указатели также можно возвращать из функций;
просто объявите возвращаемый тип функции как тип указателя.
Пример кода:
package main
import "fmt"
func createInt() *int {
var myInt = 100
return &myInt
}
func createPointer() *float64 {
var myFloat = 98.5
return &myFloat
}
func crS() *string {
var xX = "hello all"
return &xX
}
func main() {
var myFloatPointer *float64 = createPointer()
fmt.Println(*myFloatPointer)
var x *int = createInt()
fmt.Println(*x)
var x1 *string = crS()
fmt.Println(*x1)
}
Кстати говоря, в отличие от некоторых других языков, в Go можно вернуть указатель на переменную, локальную по отношению к функции.
И хотя эта переменная уже не находится в области видимости, пока у вас есть указатель, Go предоставит вам доступ к значению этой переменной.
package main
import "fmt"
func printPointer(myBoolPointer *bool) {
fmt.Println(*myBoolPointer)
}
func main() {
var myBool bool = true
printPointer(&myBool)
}
Пакет math/rand содержит функцию Intn, которая сгенерирует случайное число за нас, поэтому в программу следует импортировать math/rand.
После этого можно будет вызвать функцию rand.Intn для генерирования случайного числа
Пример кода:
package main
import (
"fmt"
"math/rand"
)
func main() {
target := rand.Intn(100) + 1
fmt.Println(target)
}
Передайте число функции rand.Intn, и функция вернет случайное число в диапазоне от 0 до переданного числа.
Другими словами, если передать аргумент 100, будет получено случайное число в диапазоне 0–99.
Так как нам требуется число в диапазоне 1–100, остается прибавить 1 к полученному случайному значению.
Результат сохраняется в переменной target.
Пока мы ограничимся простым выводом переменной target.
Попытавшись запустить программу в таком виде, вы получите случайное число.
Однако вы будете получать одно и то же случайное число раз за разом!
Чтобы получать разные случайные числа, необходимо передать значение функции rand.Seed.
Тем самым вы «инициализируйте» генератор случайных чисел, то есть предоставляете значение, которое будет использоваться для генерирования других случайных чисел.
Но если передавать одно и то же значение инициализации, то и случайные значения будут теми же и мы снова вернемся к тому, с чего начинали.
Ранее было показано, что функция time.Now выдает значение Time, представляющее текущую дату и время.
Его можно использовать для того, чтобы получать разное значение инициализации при каждом запуске программы.
Пример кода:
package main
import (
"fmt"
"math/rand"
"time"
)
func main() {
seconds := time.Now().Unix()
rand.Seed(seconds)
target := rand.Intn(100) + 1
fmt.Println(target)
}
Функция rand.Seed ожидает получить целое число, поэтому передать ей значение Time напрямую не удастся.
Вместо этого для Time следует вызвать метод Unix, который преобразует его в целое число.
(А конкретно значение будет преобразовано в формат времени Unix — целое количество секунд, прошедших с 1 января 1970 года. Впрочем, запоминать это не нужно.)
Это число передается rand.Seed.
Выражение вычисляется, и если полученный результат равен true, то выполняется код в теле условного блока.
Если же результат равен false, условный блок пропускается.
if true {
fmt.Println("I'll be printed!")
}
if false {
fmt.Println("I won't!")
}
Как и многие другие языки, Go поддерживает множественное ветвление в условных командах.
Такие команды записываются в форме if...else if...else.
if grade == 100 {
fmt.Println("Perfect!")
} else if grade >= 60 {
fmt.Println("You pass.")
} else {
fmt.Println("You fail!")
}
Условные команды используют логическое выражение (результат которого равен true или false),
чтобы определить, должен ли выполняться содержащийся в них код.
if 1 == 1 {
fmt.Println("I'll be printed!")
}
if 1 >= 2 {
fmt.Println("I won't!")
}
if 1 > 2 {
fmt.Println("I won't!")
}
if 2 <= 2 {
fmt.Println("I'll be printed!")
}
if 1 < 2 {
fmt.Println("I'll be printed!")
}
if 2 != 2 {
fmt.Println("I won't!")
}
Если код должен выполняться только в том случае, когда условие дает результат false, используйте ! — оператор логического отрицания.
Этот оператор берет значение true и превращает его в false или же берет значение false и превращает его в true.
if !true {
fmt.Println("I won't be printed!")
}
if !false {
fmt.Println("I will!")
}
Если код должен выполняться только в том случае, когда истинны оба условия, используйте оператор && («и»).
А если он должен выполняться лишь тогда, когда истинно хотя бы одно из двух условий, используйте оператор || («или»).
if true && true {
fmt.Println("I'll be printed!")
}
if false || true {
fmt.Println("I'll be printed!")
}
if true && false {
fmt.Println("I won't!")
}
if false || false {
fmt.Println("I won't!")
}
В: Другой язык программирования требует, чтобы условие команды if заключалось в круглые скобки. В Go это не обязательно?
О: Нет. Более того, команда go fmt удалит все круглые скобки, добавленные вами, если только они не используются для определения порядка операций.
Циклы / Цикл for
Пример кода:
package main
import "fmt"
func main() {
for x := 4; x <= 6; x++ {
fmt.Println("x is now", x)
}
}
Разберем:
for x := 4; x <= 6; x++ {
fmt.Println("x is now", x)
}
for - ключевое слово
x:=4 - команда инициализации
x < 6 - Условное выражение
x++ - Операция приращения
{ - начало блока цикла
}конец блока цикла
fmt.Println("x is now", x) - тело блока цикла
Циклы всегда начинаются с ключевого слова for. В одной из стандартных разновидностей циклов за for следуют три сегмента кода, которые управляют циклом:
- Команда инициализации, обычно используемая для инициализации переменной.
- Условное выражение, которое определяет, когда следует прервать выполнение цикла.
- Оператор приращения, который выполняется после каждой итерации цикла.
Команда инициализации часто используется для инициализации переменной;
условное выражение обеспечивает выполнение цикла до того, как переменная достигнет определенного значения, и оператор приращения обновляет значение этой переменной.
Например, в приведенном фрагменте переменная t инициализируется значением 3, условие обеспечивает выполнение цикла, пока t > 0,
а оператор приращения уменьшает t на 1 при каждом выполнении цикла.
В конечном итоге t уменьшается до 0 и цикл завершается.
package main
import "fmt"
func main() {
for t := 3; t > 0; t-- {
fmt.Println(t)
}
fmt.Println("Blastoff!")
}
Операторы ++ и -- часто встречаются в командах приращения циклов.
++ увеличивает значение переменной на 1, а -- уменьшает его на 1.
Примеры кода:
x := 0
x++
fmt.Println(x)
x++
fmt.Println(x)
x--
fmt.Println(x)
for x := 1; x <= 3; x++ {
fmt.Println(x)
}
for x := 3; x >= 1; x-- {
fmt.Println(x)
}
В языке Go также поддерживаются операторы присваивания += и -=.
Они получают значение в переменной, добавляют или вычитают другое значение, а затем присваивают результат той же переменной.
Примеры кода:
x := 0
x += 2
fmt.Println(x)
x += 5
fmt.Println(x)
x -= 3
fmt.Println(x)
Операторы += и -= также могут использоваться в циклах для изменения переменной на величину, отличную от 1.
for x := 1; x <= 5; x += 2 {
fmt.Println(x)
}
for x := 15; x >= 5; x -= 5 {
fmt.Println(x)
}
Когда цикл завершается, выполнение программы продолжится с команды, следующей за блоком цикла.
При этом цикл продолжает выполняться, пока условное выражение остается истинным.
Этот факт может иметь нежелательные последствия;
ниже приведены примеры циклов, которые выполняются бесконечно или не выполняются ни одного раза:
бесконечный цикл:
for x := 1; true; x++ {
fmt.Println(x)
}
Цикл не выполнится никогда:
for x := 1; false; x++ {
fmt.Println(x)
}
Будьте осторожны!
Цикл может выполняться бесконечно.
В этом случае ваша программа никогда не остановится сама.
Если это случится, в активном окне терминала нажмите клавишу Control одновременно с клавишей C, чтобы прервать выполнение программы.
Операторы инициализации и приращения необязательны.
При желании операторы инициализации и приращения в заголовке цикла for можно опустить,
оставив только условное выражение (хотя вы должны проследить за тем, чтобы условие в какой-то момент становилось ложным, иначе в программе возникнет бесконечный цикл).
x := 1
for x <= 3 {
fmt.Println(x)
x++
}
x := 3
for x >= 1 {
fmt.Println(x)
x--
}
Пропуск частей цикла командами continue и break
В Go предусмотрены два ключевых слова для управления циклом.
Первое — continue — осуществляет немедленный переход к следующей итерации цикла;
при этом дальнейший код текущей итерации в блоке цикла пропускается.
for x := 1; x <= 3; x++ {
fmt.Println("before continue")
continue
fmt.Println("after continue")
}
В приведенном выше примере строка "after continue" никогда не выводится,
потому что ключевое слово continue всегда выполняет переход к началу цикла — до того, как отработает второй вызов Println.
Второе ключевое слово break приводит к немедленному выходу из цикла. Дальнейший код в блоке цикла не отрабатывается, другие итерации цикла не выполняются.
Управление передается первой команде, следующей за циклом.
for x := 1; x <= 3; x++ {
fmt.Println("before break")
break
fmt.Println("after break")
}
fmt.Println("after loop")
Здесь при первой итерации цикла выводится сообщение "before break", после чего команда break немедленно прерывает цикл;
сообщение "after break" не выводится, и цикл не выполняется повторно (хотя без break он бы выполнился еще два раза).
Управление передается команде, следующей за циклом.