Q
Слишком короткий поисковый запрос.
По вашему запросу ничего не найдено :(
Убедитесь, что запрос написан правильно, или посмотрите другие
наши статьи:
Для системного администратора очень важно иметь корректную настройку системного времени на IP – АТС Asterisk. Важность этого обуславливается многими причинами, такими как корпоративная маршрутизация звонка по времени, отработка резервного копирования по расписанию или отработка «кастомных» скриптов в cron. В статье мы покажем как правильно настроить время через графическую оболочку FreePBX и продемонстрируем настройки NTP (Network Time Protocol) через командную строку сервера.
Настройка временной зоны через FreePBX
Перейдя в WEB - браузере к графическому интерфейсу FreePBX 13, откройте вкладку Admin → System Admin. Оказавшись в панели управления модулем, выберите необходимую временную зону (Time Zone) из предложенных:
Выбрав необходимую вам зону нажмите Submit
Обратите внимание! Чтобы настройки вступили в силу, необходимо произвести перезагрузку сервера. Вы можете сделать это либо через CLI с помощью команды reboot, либо в разделе Power Options.
Настройка NTP через CLI
Если после установки временной зоны время на вашем сервере так и не поменялось, то необходимо произвести проверку настроек NTP. Подключитесь к серверу по SSH или напрямую, и выполните следующие команды:
[root@localhost ~]# vim /etc/ntp.conf
Проверьте содержимое файла настройки синхронизации времени. В нем в явном виде должны быть прописаны сервера (не закомментированные строки, начинающиеся с server). Если вы хотите указать собственный сервер NTP, то сотрите содержимое файла и добавьте запись. Формат примерно такой:
server 192.168.0.123 //вместо 192.168.0.123, укажите IP – адрес или доменное имя вашего NTP
Перед изменением конфигурации файла ntp.conf рекомендуем проверить сетевую связность, произведя пинг – запрос на IP или доменное имя сервера.
После проверки конфигурации, проверяем запущен ли NTP демон на сервере:
[root@localhost ~]# service ntpd status
ntpd (pid 1234) is running...
Как мы видимо, процесс ntpd с идентификатором 1234 запущен. Если у вас иначе, произведите перезапуск этого процесса:
[root@localhost ~]# service ntpd restart
Shutting down ntpd: [ OK ]
Starting ntpd: [ OK ]
Далее убеждаемся, что ntpd будет автоматически запускать при загрузке нашего сервера:
[root@localhost ~]# chkconfig ntpd on
[root@localhost ~]#
Проверяем, с какими NTP серверами синхронизируется наш Asterisk:
[root@localhost ~]# ntpq -p
remote refid st t when poll reach delay offset jitter
==============================================================================
-n2.time1.regnet 194.190.168.1 2 u 46 64 37 50.668 6.009 2.017
Через некоторое время проверяем системное время командой date. Теперь все должно быть корректно:
[root@localhost ~]# date
Mon Oct 24 12:53:06 MSK 2016
В предыдущих статьях мы познакомились как управлять ресурсами AWS с помощью Terraform, в данной статье мы посмотрим, как создавать работающий web-сервер с помощью Terraform. Для развертывания настоящего боевого Web сервера, нам понадобится создать с помощью Terraform два ресурса. Инстанс EC2 и группу безопасности для того, чтобы открыть порт 80 во внешний мир. Для начала создадим новую директорию Lesson-2 и файл WebServer.tr. Вспоминаем именно данный файл с данным расширением является основным для написания кода и управления.
Напоминаю, что это обычный текстовый файл, который редактируется с помощью любого текстового редактора в нашем случае мы будем использовать текстовый редактор nano.
Mkdir Lesson-2
cd Lesson-2
nano WebServer.tr
Сразу будем привыкать к оформлению кода и добавим в код комментарии, комментарии добавляются следующим образом. Ставим знак решетки # и за ней пишем комментарий.
#-----------------------------------------------
# Terraform
#
#Build WebServer during BootStrap
#--------------------------------------------------
Для начала пишем, кто провайдер и регион для размещения наших ресурсов.
provider "aws" {
region = "eu-central-1"
}
Кстати, есть интересный сайт awsregion.info на котором можно посмотреть название регионов и место размещение. Сайт на момент написания статьи обновляется и поддерживается в актуальном состоянии.
Так первый ресурс это инстанс EC2. Resource служебное слово, далее название ресурса в кавычках и имя, которое мы ему даем в кавычках, далее открываются и закрываются фигурные скобки. Именно между ними мы и будем описывать наш ресурс.
Далее добавляем ami – который показывает, какой образ мы будем использовать.
Instance_type – тип и размер ресурса, который мы будем использовать.
В итоге смотрим, что у нас получилось в первой итерации кода:
resource "aws_instance" "WebServer_my" {
ami = "ami-0767046d1677be5a0" #Amazon Linux ami
instance_type = "t2.micro"
}
В результате исполнения данной части у нас будет создан инстанс EC2.
Далее создадим 2-й ресурс aws_security_group, фактически это правило сети для брандмауэра.
Так же описание начинаем со служебного слова resource, далее название ресурса и имя ресурса в кавычках, а в конце открывающаяся и закрывающаяся скобка в которой пойдет описание ресурса. Указываем параметр name - этот параметр обязательный для корректного отображения, description – параметр не обязательный, но можем указать, vpc_id мы не указываем т.к используем ресурс vpc по умолчанию. Далее идет описание правил сетевых на языке Terraform. Служебный параметр ingress для входящего трафика с фигурными скобками где мы вставим порты и другие параметры данного параметра. И второй служебный параметр engress для исходящего трафика с фигурными скобками. Cidr_blocks = [“подсеть”], указывают откуда или куда разрешен данный поток трафика т.е подсеть 0.0.0.0/0 означает весь интернет или все подсети.
Обратите внимание:
Мы разрешили входящий трафик на 80 порт, тот порт на котором будет работать наш веб сервер.
Мы разрешили входящий трафик на 22 порт, тот порт, который может принимать соединение для подключения по SSH протоколу.
Мы разрешили ICMP трафик до нашего сервера, чтобы можно было из интернета проверить его доступность.
Мы разрешили трафик на 443 порт, если мы в будущем захотим сделать защищенное HTTPS соединение.
И мы разрешили весь исходящий трафик с сервера указав protocol “-1”
В такой конфигурации кода Terraform мы получим два отдельных ресурса Инстанс EC2 и группу безопасности, но нас такой вариант не устроит. Нам необходимо, чтобы данная группа безопасности была автоматически присоединена к нашему серверу. Это можно сделать с помощью нового параметра, который мы добавим в первую часть кода, где мы описывали aws_instance. Данный параметр называется vpc_security_group_id, с помощью данного параметра можно сразу присоединить несколько групп безопасности, через знак равенства и скобки “= [“номер группы безопасности”]”. Например, номер группы безопасности можно взять той, что создается по умолчанию.
Все остальные указываются, через запятую. Но в нашем случае данный вариант не подойдет, потому что у нас должно все подключиться автоматически, т.е присоединить ту группу безопасности, которая создастся и которую мы описали ниже. А делается это достаточно просто после знака = в квадратных скобках без кавычек вставляем aws_security_group – то что это группа безопасности, затем . – разделитель, затем вставляем имя группы безопасности, которую мы создали mywebserver, опять разделитель символ точки ., и мы ходим взять id. В итоге получается следующий параметр и его значение:
vpc_security_group_ids = [aws_security_group.mywebserver.id]
Этой самой строчкой мы привязали группу безопасности к нашему создаваемому инстансу. И как следствие возникла зависимость инстанса от группы безопасности. Следовательно, Terraform создаст сначала группу безопасности, а затем уже создаст инстанс.
Код Terraform не выполняется сверху вниз, зачастую он исполняется в зависимости от зависимостей или вообще одновременно, когда многие части зависят друг от друга. Следовательно, вот в таком коде мы создали зависимость. По коду вы можете заметить, что если необходимо еще дополнительный порт открыть, например, в группе безопасности, то необходимо скопировать часть кода, отвечающую за открытие порта и добавить необходимые настройки, порт и протокол, подправить cidr_blocks. После корректировки вставить в правильное место, как параметр.
И для того, чтобы завершить настройку нашего Web сервера, нам необходимо написать параметр user_data. В амазоне это называется bootstrapping, т.е начальная загрузка.
User_data = <<EOF
Скрипт
EOF
Как вы видите сам скрипт будет находится между EOF, а знак << говорит о том, что скрипт мы подаем на ввод.
Далее, как любой скрипт в Linux системе мы пишем сначала интерпретатор или shell который будет исполнять и на языке понятном для bash. Поэтому в скрипте не должно быть никаких отступов! Это важно, даже если плагин текстового редактора пытается поправить.
Теперь сам скрипт:
user_data = <<EOF
#!/bin/bash
apt -y update
apt -y install apache2
myip=`curl http://169.254.169.254/latest/meta-data/local-ipv4`
echo "<h2>WebServer with IP: $myip</h2><br> Build by Terraform!" > /var/www/html /index.html
sudo service httpd start
chkconfig httpd on
EOF
Сначала обновляем систему apt –y update, далее команда apt –y install apache2 устанавливаем apache веб сервер непосредственно. Следующая строка присваиваем значение переменной myip, с помощью получения данных из самого амазона curl http://169.254.169.254/latest/meta-data/local-ipv4. Далее просто добавляем в индексную страницу по умолчанию вывод того что мы получили с подстановкой IP. Следующая строка стартует сервис, и последняя строка проверяет конфигурацию апача.
Таким образом, мы получаем полностью готовый скрипт. Нам остается его сохранить в файле и инициализировать Terraform, командой terraform init и даем команду на применение terraform apply.
В результате команды мы видим, что будет создано 2 ресурса, все, как и планировалось. Инстанс и группа безопасности.
Как мы видим сначала, из-за зависимости создается группа безопасности. А затем поднимается инстанс, к которому и будет привязана данная группа. Спустя пару минут мы можем видеть, что у нас веб сервер поднялся.
IP-адрес можно найти в консоли.
Далее, если нам более данный Web сервер не нужен, то мы его можем уничтожить простой командой terraform destroy. И мы увидим, что из-за зависимостей ресурсы будут уничтожаться в обратном порядке тому, в котором они запускались. Сначала инстанс, потом группа безопасности.
Скрипт вы можете легко модифицировать и добавить более сложные детали установки и настройки веб сервера – это полностью рабочая конфигурация.
«Любой дурак может написать код, который поймет компьютер. Хорошие программисты пишут код, который поймут люди», - Мартин Фаулер.
Каждый разработчик, который хочет стать профессионалом, должен овладеть навыком написания чистого, понятного и удобного в сопровождении кода.
В этой статье мы рассмотрим самые важные принципы повышения качества кода, и я также покажу вам несколько примеров.
Большую часть примеров я взял из книги Роберта Дж. Мартина «Чистый код». Это классика программирования, и я бы рекомендовал вам прочитать ее полностью, когда у вас будет время.
Как давать имена переменным (и прочее)
«Есть только две сложные вещи в компьютерных науках: аннулирование элементов кэша и присвоение имен сущностям», - Фил Карлтон.
Не просто так мы используем имена вместо адресов ячеек памяти – имена гораздо проще запоминать. И, более того, они могут дать гораздо больше информации о переменной, чтобы кто-нибудь другой мог понять, что в ней хранится и для чего она нужна.
Да, поиск хорошего имени может занять какое-то время, но это сэкономит вам и вашей команде еще больше времени в будущем. И я уверен, что большая часть читателей сталкивалась с проблемой, когда при просмотре своего же кода буквально спустя несколько месяцев, вы с трудом понимали, что вы тогда делали.
Как создавать смысловые имена
Не используйте комментарии, чтобы пояснить, для чего нужна переменная. Если имя было создано так, что оно требует комментария, то вам следует еще раз подумать и переименовать ее, а не писать комментарий.
«Имя должно говорить о том, для чего переменная существует, что она делает и как ее использовать. Если имя требует комментария, то оно не отображает ее смысла», - «Чистый код».
Плохой вариант:
var d; // elapsed time in days
Я видел такой вариант написания не раз. Это всеобщее заблуждение думать, что вы можете скрыть свою неразбериху с помощью комментариев. Не используйте такие буквы, как x, y, a или b, в качестве имен переменных, только если для этого нет веской причины (исключением здесь являются переменные цикла).
Хороший вариант:
var elapsedTimeInDays;
var daysSinceCreation;
var daysSinceModification;
Такой вариант намного лучше. Здесь имена переменных говорят нам о том, что измеряется и в каких единицах.
Не допускайте дезинформации
Будьте внимательными со словами, у которых есть конкретное значение. Не нужно называть группу учетных записей
accountList
, если на самом деле ее тип не имеет никакого отношения к списку. Слово имеет определенное значение, и это может привести к ошибочным заключениям.
Даже если это на самом деле список, то в любом случае лучше просто оставить
accounts
.
Плохой вариант:
var accountList = [];
Хороший вариант:
var accounts = []
Избегайте использования пропускаемых слов
Пропускаемые слова – это слова, которые не несут никакой дополнительной информации о переменной. Они являются излишними, и их стоит удалить.
Ниже приведен список некоторых популярных пропускаемых слов:
the (префикс)
info
data
variable
object
manager
Если ваш класс называется UserInfo, то слово Info можно удалить, достаточно оставить User. И не нужно быть семь пядей во лбу, чтобы использовать BookData вместо Book в качестве имени класса, поскольку класс в любом случае хранит данные.
Используйте легкопроизносимые имена
Если вы не можете произнести имя переменной, то вы не сможете обсуждать ее так, чтобы это не звучало нелепо.
Плохой вариант:
const yyyymmdstr = moment().format("YYYY/MM/DD");
Хороший вариант:
const currentDate = moment().format("YYYY/MM/DD");
Используйте имена с возможностью поиска
Не используйте волшебные чисел в вашем коде. Отдайте предпочтение именованным константам с возможностью поиска. Не используйте односимвольные имена для констант, поскольку они могут много где встречаться, и, следовательно, их не просто будет найти.
Плохой вариант:
if (student.classes.length < 7) {
// Do something
}
Хороший вариант:
if (student.classes.length < MAX_CLASSES_PER_STUDENT) {
// Do something
}
Такой вариант будет гораздо лучше, поскольку переменная
MAX_CLASSES_PER_STUDENT
может использоваться в нескольких местах кода. Если в дальнейшем нам потребуется заменить ее на 6, то мы сможем просто изменить константу.
Глядя на плохой вариант, у читателя могут возникнуть вопросы, например, какова степень важности числа 7?
Вы также должны использовать соглашения о присвоении имен константам и их объявлении, такие как
private static final
в Java или
const
в JavaScript.
Будьте логичными
Всегда следуйте правилу: «
одно слово на каждое концептуальное представление
». Не нужно использовать
fetch
,
retrieve
и
get
для одних и тех же операций в разных классах. Выберите что-то одно и используйте его на протяжении всего проекта, чтобы люди, сопровождающие кодовую базу, или клиенты вашего API могли с легкостью отыскать методы, которые им нужны.
Как писать функции
Помните о том, что они должны быть небольшими
Функции должны быть небольшими, от слова совсем. Они редко бывают длиной более 20 строк. Чем длиннее функция, тем больше вероятность того, что она будет выполнять несколько действий и будет иметь побочные эффекты.
Убедитесь, что они выполняют только одно действие
«Функции должны выполнять только одно действие. И они должны делать это хорошо. И делать это должны только они», - «Чистый код».
Ваши функции должны отвечать только за одно действие. Если вы будете следовать этому правилу, то они гарантированно будут небольшими. То единственное, что выполняет функция, должно отображаться в ее имени.
Иногда бывает сложно понять, глядя на функцию, сколько действий она выполняет. Отличный способ узнать – попробовать выделить другую функцию с другим именем. Если у вас получится, то это значит, что это должна быть другая отдельная функция.
Возможно, это самая важная концепция в данной статье, и пройдет какое-то время, прежде чем вы к ней привыкнете. Но как только вы набьете руку, ваш код будет выглядеть более полноценным, и его легче будет реорганизовывать, понимать и тестировать.
Инкапсулируйте условные конструкции в функциях
Реорганизация условий и помещение их в именованную функцию – отличный способ сделать ваши условные конструкции более читабельными.
Ниже я привел фрагмент кода из моего школьного проекта. Он отвечает за добавление фишки на поле игры Connect 4.
Метод
isValidInsertion
отвечает за проверку корректности номера столбца, и за счет этого мы можем уделить больше внимания логике добавления фишки.
public void insertChipAt(int column) throws Exception {
if (isValidInsertion(column)) {
insertChip(column);
boardConfiguration += column;
currentPlayer = currentPlayer == Chip.RED ? Chip.YELLOW : Chip.RED;
} else {
if (!columnExistsAt(column))
throw new IllegalArgumentException();
else if (isColumnFull(column - 1) || getWinner() != Chip.NONE)
throw new RuntimeException();
}
}
Ниже я привел код для метода isValidInsertion (если вам интересно).
private boolean isValidInsertion(int column) {
boolean columnIsAvailable = column <= NUM_COLUMNS && column >= 1 && numberOfItemsInColumn[column - 1] < NUM_ROWS;
boolean gameIsOver = getWinner() != Chip.NONE;
return columnIsAvailable && !gameIsOver;
Без этого метода условие if выглядело бы вот так:
if (column <= NUM_COLUMNS
&& column >= 1
&& numberOfItemsInColumn[column - 1] < NUM_ROWS
&& getWinner() != Chip.NONE)
Ужасно, не правда ли? Я думаю, да.
Поменьше аргументов
У функций должно быть не более двух аргументов, чем меньше, тем лучше. По мере возможности не допускайте использование трех и более аргументов.
Аргументы затрудняют чтение и понимание функции. К тому же, большое количество аргументов усложняет тестирование, так как появляется необходимость писать тестовые сценарии для каждой комбинации аргументов.
Не используйте аргументы типа флаг
Аргумент типа флаг – это логический аргумент, который передается функции. В зависимости от значения этого аргумента выполняется одно из двух действий. Допустим, у нас есть функция, которая отвечает за бронирование билетов на концерт и есть два вида пользователей: Premium и Regular. Код примерно следующий:
public Booking book (Customer aCustomer, boolean isPremium) {
if(isPremium)
// logic for premium book
else
// logic for regular booking
}
Аргументы типа флаг, конечно же, противоречат принципу единственной обязанности. Если вы их видите, то стоит задуматься о том, что надо разделить функции на две.
Отсутствие побочных эффектов
Побочные эффекты – это непредусмотренные последствия работы вашего кода. Они могут менять переданные параметры, если вы передаете их по ссылке, или, быть может, даже глобальную переменную.
Ключевой момент заключается в том, что функции были предназначены для другой цели, и для того, чтобы найти побочный эффект, вам нужно внимательно просмотреть код. Они могут привести к довольно неприятным ошибкам.
Ниже приведен пример из книги:
public class UserValidator {
private Cryptographer cryptographer;
public boolean checkPassword(String userName, String password) {
User user = UserGateway.findByName(userName);
if (user != User.NULL) {
String codedPhrase = user.getPhraseEncodedByPassword();
String phrase = cryptographer.decrypt(codedPhrase, password);
if ("Valid Password".equals(phrase)) {
Session.initialize();
return true;
}
}
return false;
}
}
Вы уже заменили побочный эффект этой функции?
Она проверяет пароль, но в случае, если пароль является действительным, она все равно инициализирует сеанс – это и есть побочный эффект.
Вы, конечно, можете поменять имя функции на что-то вроде
checkPasswordAndInitializeSession
, чтобы явно определить этот эффект. Но когда вы это сделаете, вы должны будете заметить, что на самом деле ваша функция выполняет два действия, и вам не стоит инициализировать сеанс в этой функции.
Не повторяйтесь
Повторяемый код – корень всех зол в программном обеспечении. Дублированный код подразумевает, что если появляются какие-то изменения в логике, то вам нужно будет внести изменения в нескольких местах, а это может поспособствовать появлению ошибок.
Используйте средства перепроектирования кода вашей IDE и выделяйте метод каждый раз, когда вы находите повторяющиеся сегменты кода.
Выделение метода в IntelliJ
Бонус
Не оставляйте код в комментариях
Сделайте одолжение, не нужно этого делать. Это важно, поскольку другие люди, которые увидят этот код, побоятся удалить его, так как не будут знать, нужен он для чего-то или нет. Этот закомментированный код останется надолго. А потом, когда имена переменных или методов изменятся, он станет бесполезным, но его все равно никто не удалит.
Поэтому просто удалите его, даже если он был важен. Вы всегда сможете его найти – для этого есть управление версиями.
Узнайте соглашения вашего языка
Вы должны знать соглашения вашего языка в отношении пробелов, комментариев и имен. Существуют руководства по стилю оформления для многих языков.
Например, в Java следует использовать camelCase, а в Python – snake_case. В C# вы ставите открывающие фигурные скобки на новой строке, но в Java и JavaScript вы ставите их на ту же строку.
Такие вещи могут отличаться в зависимости от языка, и какого-то универсального стандарта нет.
Заключение
Написание «чистого программного кода» - это не тот навык, которым можно овладеть за одну ночь. Это привычка, которую необходимо тренировать, соблюдая эти принципы и применяя их каждый раз, когда вы пишете код.
