Архив метки: FreeBSD

Оптимизация FreeBSD для XenServer, ZFS в качестве корневой файловой системы.

Имеем FreeBSD 9.2 RELEASE установленную в XenServer 6.2 — корневая файловая система ZFS. Задача установить xen-tools для полной оптимизации системы.
Исправляем файл:

/usr/src/sys/kern/subr_autoconf.c

Комментируем строку 136 и 145.

/*      while (!TAILQ_EMPTY(&intr_config_hook_list)) { */
                if (msleep(&intr_config_hook_list, &intr_config_hook_lock,
                    0, "conifhk", WARNING_INTERVAL_SECS * hz) ==
                    EWOULDBLOCK) {
                        mtx_unlock(&intr_config_hook_lock);
                        warned++;
                        run_interrupt_driven_config_hooks_warning(warned);
                        mtx_lock(&intr_config_hook_lock);
                }
/*      } */

Читать далее

Перевод ZFS mirror-0 с 512 байт сектора на 4K (ashift: 9 — ashift: 12).

Имеем FreeBSD 9.1 RELEASE amd64 установка которой производилась следующим скриптом:

#!/bin/sh
umount -f /dev/md1
mdmfs -s 512M md1 /tmp
sysctl kern.geom.debugflags=0x10
/bin/dd if=/dev/zero of=/dev/ada0 bs=1024k count=10
/bin/dd if=/dev/zero of=/dev/ada1 bs=1024k count=10
sleep 10
zpool create -f zroot mirror ada0 ada1
zpool set bootfs=zroot zroot
zfs set checksum=fletcher4 zroot
zfs set mountpoint=/mnt zroot
zpool export zroot
zpool import -o cachefile=/tmp/zpool.cache zroot
zfs create zroot/usr
zfs create zroot/usr/home
zfs create zroot/var
zfs create zroot/wwwroot
zfs create zroot/nfsroot
zfs create zroot/tmp
zfs create zroot/usr/ports
zfs create zroot/usr/ports/distfiles
zfs create zroot/usr/ports/packages
zfs create zroot/usr/src
zfs create zroot/var/crash
zfs create zroot/var/db
zfs create zroot/var/db/mysql
zfs create zroot/var/db/pkg
zfs create zroot/var/empty
zfs create zroot/var/log
zfs create zroot/var/mail
zfs create zroot/var/run
zfs create zroot/var/tmp
zfs create -V 4G -o org.freebsd:swap=on -o volblocksize=4K -o checksum=off zroot/swap
chmod 1777 /mnt/tmp
chmod 1777 /mnt/var/tmp
cd /mnt ; ln -s usr/home home
echo "install ..."
sleep 10
cd /usr/freebsd-dist
export DESTDIR=/mnt
for file in base.txz lib32.txz kernel.txz doc.txz src.txz; do (cat $file | tar --unlink -xvpJf - -C ${DESTDIR:-/}); done
echo "install ok"
sleep 1
cp /tmp/zpool.cache /mnt/boot/zfs/zpool.cache
echo 'zfs_enable="YES"' >> /mnt/etc/rc.conf
echo 'zfs_load="YES"' >> /mnt/boot/loader.conf
echo 'vfs.root.mountfrom="zfs:zroot"' >> /mnt/boot/loader.conf
echo '#vm.kmem_size="512M"' >> /mnt/boot/loader.conf
touch /mnt/etc/fstab
zfs set readonly=on zroot/var/empty
zfs umount -a
zfs set mountpoint=legacy zroot
zfs set mountpoint=/tmp zroot/tmp
zfs set mountpoint=/usr zroot/usr
zfs set mountpoint=/var zroot/var
zfs set mountpoint=/wwwroot zroot/wwwroot
zfs set mountpoint=/nfsroot zroot/nfsroot
/bin/dd if=/boot/zfsboot of=/dev/ada0 count=1
/bin/dd if=/boot/zfsboot of=/dev/ada1 count=1
/bin/dd if=/boot/zfsboot of=/dev/ada0 skip=1 seek=1024
/bin/dd if=/boot/zfsboot of=/dev/ada1 skip=1 seek=1024

Поскольку ZFS устанавливался на сырые диски — все установилось с размером сектора 512 байт (ashift: 9).

ada0: <WDC WD1003FBYX-01Y7B1 01.01V02> ATA-8 SATA 2.x device
ada0: 300.000MB/s transfers (SATA 2.x, UDMA5, PIO 8192bytes)
ada0: 953869MB (1953525168 512 byte sectors: 16H 63S/T 16383C)
ada1: <Hitachi HDS721010CLA332 JP4OA3MA> ATA-8 SATA 2.x device
ada1: 300.000MB/s transfers (SATA 2.x, UDMA5, PIO 8192bytes)
ada1: 953869MB (1953525168 512 byte sectors: 16H 63S/T 16383C)
 # zdb | grep ashift
            ashift: 9

Поставил себе задачу перевести пул на использование 4К секторов (ashift: 12) и GPT меток с сохранением данных и минимальным временем простоя.
Читать далее

Резервное копирование базы MySQL.

Создаем скрипт.

#!/bin/sh
datafile=`date +%Y.%m.%d`
/usr/local/bin/mysqldump -uroot -pPASSWORD --all-databases -q | bzip2 > /backup/alldb_backup_${datafile}.bz2

Настраиваем запуск по cron (crontab -e).

0       5       *       *       *       /usr/local/etc/cron/mysql_backup.sh

PuTTY — увеличение количества строк терминала.

При использовании программы PuTTY — часто необходимо подглядеть что-то в терминале — ан нет — по умолчанию история терминала всего 200 строк. Увеличиваем до 20000.

Windows Registry Editor Version 5.00

[HKEY_CURRENT_USER\Software\SimonTatham\PuTTY\Sessions\Default%20Settings]
"ScrollbackLines"=dword:00004e20

FreeBSD — узнать размер каталога.

Как узнать размер каталога? Используем команду du.
Смотрим размер конкретного каталога.

# du -hs /usr
3.6G    /usr

Смотрим размер каталога и размер каждой папки если есть.

# du -hd 1 /usr
1.5k    /usr/games
 74M    /usr/bin
702M    /usr/src
 19M    /usr/include
1.1G    /usr/obj
 73M    /usr/lib
987M    /usr/ports
568M    /usr/local
 58M    /usr/lib32
 30M    /usr/sbin
 40M    /usr/share
 15M    /usr/libexec
123k    /usr/libdata
1.5k    /usr/home
3.6G    /usr

Не забываем пользоваться man.

man du

FreeBSD — использование ZFS в качестве корневой файловой системы.

Грузимся с загрузочного диска FreeBSD 9.0 RELEASE — выбираем shell.

Создаем разделы, записываем загрузчик.

gpart create -s gpt da0
gpart add -b 34 -s 94 -t freebsd-boot da0
gpart add -t freebsd-zfs -l disk0 da0
gpart bootcode -b /boot/pmbr -p /boot/gptzfsboot -i 1 da0

Создаем ZFS пул игнорируя предупреждения.

zpool create zroot /dev/gpt/disk0

Устанавливаем дополнительные параметры, указываем временную точку монтирования.

zpool set bootfs=zroot zroot
zfs set checksum=fletcher4 zroot
zfs set mountpoint=/mnt zroot

Экспортируем и импортируем пул.

zpool export zroot
zpool import -o cachefile=/var/tmp/zpool.cache zroot

Создаем файловые системы на свой вкус и цвет.

zfs create zroot/usr
zfs create zroot/usr/home
zfs create zroot/var
zfs create -o compression=on -o exec=on -o setuid=off zroot/tmp
zfs create -o compression=lzjb -o setuid=off zroot/usr/ports
zfs create -o compression=off -o exec=off -o setuid=off zroot/usr/ports/distfiles
zfs create -o compression=off -o exec=off -o setuid=off zroot/usr/ports/packages
zfs create -o compression=lzjb -o exec=off -o setuid=off zroot/usr/src
zfs create -o compression=lzjb -o exec=off -o setuid=off zroot/var/crash
zfs create -o exec=off -o setuid=off zroot/var/db
zfs create -o compression=lzjb -o exec=on -o setuid=off zroot/var/db/pkg
zfs create -o exec=off -o setuid=off zroot/var/empty
zfs create -o compression=lzjb -o exec=off -o setuid=off zroot/var/log
zfs create -o compression=gzip -o exec=off -o setuid=off zroot/var/mail
zfs create -o exec=off -o setuid=off zroot/var/run
zfs create -o compression=lzjb -o exec=on -o setuid=off zroot/var/tmp

Добавляем swap раздел.

zfs create -V 4G zroot/swap
zfs set org.freebsd:swap=on zroot/swap
zfs set checksum=off zroot/swap

Создаем линк, исправляем разрешения.

chmod 1777 /mnt/tmp
cd /mnt ; ln -s usr/home home
chmod 1777 /mnt/var/tmp

Установка FreeBSD.

sh
cd /usr/freebsd-dist
export DESTDIR=/mnt
for file in base.txz lib32.txz kernel.txz doc.txz ports.txz src.txz;
do (cat $file | tar --unlink -xpJf - -C ${DESTDIR:-/}); done

Копирование zpool.cache.

cp /var/tmp/zpool.cache /mnt/boot/zfs/zpool.cache

Создание rc.conf, loader.conf и пустого fstab.

echo "zfs_enable=YES >> /mnt/etc/rc.conf
echo "zfs_load=YES; >> /mnt/boot/loader.conf
echo "vfs.root.mountfrom=zfs:zroot >> /mnt/boot/loader.conf
touch /mnt/etc/fstab

Установка точек монтирования.

zfs set readonly=on zroot/var/empty
zfs umount -af
zfs set mountpoint=legacy zroot
zfs set mountpoint=/tmp zroot/tmp
zfs set mountpoint=/usr zroot/usr
zfs set mountpoint=/var zroot/var

Перезагружаемся.

reboot

Дабы не ошибиться в наборе команд, можно сделать следующее — создать скрипт. Разместить его на любой машине куда имеется доступ оп ssh.
Настраиваем сетевой интерфейс.

ifconfig em0 inet 192.168.0.2 netmask 255.255.255.0 up

Выполняем скрипт:

ssh user@192.168.0.1 'cat zfs.sh' | sh

FreeBSD настройка ftpd.

Настраиваем штатный ftpd для FreeBSD 9.0 RELEASE.

Добавляем группу и пользователя ftp. Открываем файл /etc/group — добавляем группу ftp.

ftp:*:21:

Файл /etc/master.passwd — добавляем пользователя ftp.

ftp:*:21:21::0:0:FTPD pseudo-user:/wwwroot/pub:/usr/sbin/nologin

Обновляем базу пользователей вручную.

pwd_mkdb -p /etc/master.passwd

Создаем домашний каталог пользователя для анонимного ftp доступа если необходимо.

mkdir /wwwroot
mkdir /wwwroot/ftp

Меняем владельца и права.

chown ftp:ftp /wwwroot/ftp
chmod 555 /wwwroot/ftp

Добавляем в /etc/rc.conf следующие строчки для запуска в режиме демона.

ftpd_enable="YES"
ftpd_flags="-l"

Запускаем.

/etc/rc.d/ftpd start

проверяем что получилось.

# ps -x | grep ftpd
22255  ??  Is      0:00.00 /usr/libexec/ftpd -D -l
22371   0  S+      0:00.00 grep ftpd

Второй способ — через inetd — по факту не используется. В /etc/rc.conf добавляем

inetd_enable="YES"

и раскоментируем строчку в файле /etc/inetd.conf

ftp    stream  tcp     nowait  root    /usr/libexec/ftpd       ftpd -l

и даем команду

/etc/rc.d/inetd start

Результат — мы настроили анонимный FTP сервер, анонимный пользователь может только читать, логи подключений пишутся в файл по умолчанию /var/log/xferlog.
Дополнительные настройки.
/etc/ftpwelcome – приветственное сообщение выводимое сервером до ввода логина и пароля.
/etc/ftpmotd – приветственное сообщение, выводимое при удачном входе на сервер.
/etc/ftphosts – настройка виртуальных хостов.
/etc/ftpchroot — настройка chroot для пользователей. Например для пользователя test делать chroot в каталог /wwwroot/test/html, для всех пользователей группы ftptest — chroot в каталог /wwwroot/test, для пользователей группы www — chroot в свои домашние каталоги.

test /wwwroot/test/html
@ftptest /wwwroot/test
@www

Незабываем про настройку файервола если используется, дополнительно можно воспользоватся настройками в файле /etc/hosts.allow для разрешения/запрещения коннектов с тех или иных адресов.

ftpd : localhost : allow
ftpd : 192.168.4.23 : deny
ftpd : .nice.guy.example.com : allow
ftpd : .evil.cracker.example.com : deny
ftpd : ALL : allow

Но помним — проблемы с настройкой пассивного режима работы — актуально если необходимо обслуживать соединения из-за NAT.

Дополнительные ключи ftpd.

-4      Когда указана опция -D, принимать соединения через сокет AF_INET.

-6      Когда указана опция -D, принимать соединения через сокет AF_INET6.

-8      Разрешить прозрачный режим UTF-8. Клиенты, совместимые со стандартом RFC 2640 оповещаются об использовании сервером символов в кодировке UTF-8. Эта опция не включает любые перекодировки имен файлов сервера; это работает для имен файлов сервера, закодированных в UTF-8. При выкачке (upload) файлов на FTP включается для клиентов, совместимых с RFC 2640, перекодировка из локальной кодировки клиента в UTF-8. FTP команды и собственные сообщения ftpd в любом случае кодируются в ASCII, который является подмножеством UTF-8. Следовательно, здесь не нужна перекодировка на сервере.

-A      Разрешается только анонимный доступ к ftp.

-a      Когда указана опция -D, соединения принимаются только от указанного адреса.

-D      Когда указана эта опция, ftpd отсоединяется от консоли и становится демоном, принимающим соединения через порт FTP и порождающим (forking) дочерние процессы для поддержки запросов. Это обеспечивает меньшие траты ресурсов в сравнении с запуском ftpd через inetd(8) и полезно для применения на нагруженных серверах для уменьшения нагрузки.

-d      Отладочная информация будет записываться в лог с изпользованием LOG_FTP.

-E      Запретить команду EPSV. Это хорошо применять для серверов за файерволом.

-h      Запрет вывода в сообщениях сервера информации, специфичной для хоста, такой как версия ПО сервера или имя хоста.

-l      Каждая успешная и ошибочная ftp(1) сессия записывается через syslog LOG_FTP. Если эта опция указана дважды, то записыватся команды retrieve (get), store (put), append, delete, make directory, remove directory и операции rename вместе с именами файлов и аргументами. По умолчанию, syslogd(8) записывает эти сообщения в /var/log/xferlog.

-M      Предотвращает создание анонимными (anonymous) пользователями директорий.

-m      Разрешает анонимным пользователям перезаписывать или модифицировать существующие файлы, если это разрешено правами файловой системы. По умолчанию anonymous не может модифицировать существующие файлы; в частности, файлы для выгрузки на сервер (upload) должны создаваться с уникальными именами.

-O      Переводит сервер а режим write-only только для anonymous. Команда RETR запрещена для anonymous, что предотвращает анонимные загрузки (downloads) с сервера. Не дает эффекта, если также указана опция -o.

-o      Переводит сервер а режим write-only. Команда RETR запрещена для всех, что предотвращает загрузку информации с сервера.

-P      Когда указана опция -D, принимает соединения на указанном порту, указанном как числовая величина или имя сервиса, вместо порта «ftp» по умолчанию.

-p      Когда указана опция -D, записывает файл process ID в указанный файл вместо pid-файла по умолчанию /var/run/ftpd.pid.

-R      Когда указана эта опция, ftpd возвращается к историческому поведению по отношения к проверкам безопасности операций пользователей и ограничениям по запросам PORT. В настоящий момент ftpd поддерживает только команды PORT, направленные на непривилегированные порты для удаленных пользователей хоста (которые нарушают спецификацию протокола FTP, однако закрывают некоторые дыры в безопасности).

-r      Переводит сервер с режим read-only (только для чтения). Все команды, которые могут модифицировать файловую систему, запрещены.

-S      Когда указана эта опция, ftpd пишет в лог /var/log/ftpd все загрузки файлов anonymous, если этот файл лога существует.

-T      Клиент может также запрашивать отличеющийся период таймаута; максимально разрешенный период таймаута, который может быть установлен, задается опцией -T в секундах. Лимит по умолчанию 2 часа.

-t      Таймаут неактивности в секундах (по умолчанию 15 минут).

-U      Эта опция инструктирует ftpd использовать порты данных в диапазоне IP_PORTRANGE_DEFAULT вместо IP_PORTRANGE_HIGH. Это изменение полезно для некоторых специфичных конфигураций файерволла; см. ip(4) для дополнительной информации.

Примите к сведению, что эта опция является виртуальной и не работает на FreeBSD 5.0 выше; оба диапазона портов на них по умолчанию идентичны.

-u      Маска создания режима файла по умолчанию (file creation mode mask) устанавливается в umask, которая ожидается в восьмеричной числовой величине. См. umask(2) для деталей. Эта опция может быть переустановлена (запрещена) через login.conf(5).

-v      Синоним -d.

-W      Не записывать в лог /var/log/wtmp сессии FTP.

Как определить размер памяти во FreeBSD

Внезапно оказалось, что во FreeBSD нет способа быстро и наглядно посмотреть размер физической, свободной и занятой памяти. Вроде команды ‘free’ в линуксе. Интернет полон вопросами на этот счет и в ответ предлагается либо грепать дмесг:

# dmesg | grep memory
real memory  = 2147483648 (2048 MB)
avail memory = 2045009920 (1950 MB)
real memory  = 2147483648 (2048 MB)
avail memory = 2045009920 (1950 MB)

Либо ставить из портов ‘freecolor’:

# uname -omr
FreeBSD 9.0-RELEASE amd64
# cd /usr/ports/sysutils/freecolor/
freebsd# make install clean
===>  freecolor-0.8.8 is marked as broken: Does not function correctly on !i386.
*** Error code 1
Stop in /usr/ports/sysutils/freecolor.

Пичалька. Либо скачать и использовать вот этот перловый скрипт.

Ад и ненависть наполняет автора оригинального поста найденного мной тут, так как использовать пёрл для такой простой задачи — это нарушать KISS-принцип, ломать бритву Оккама лишней сущностью, а также просто фэйл. Плюс скрипт не обрабатывает ситуацию запуска из jail-а, что в наше время адской виртуализации всего — неприемлемо. Всяческие ‘top’ и ‘vmstat’ не велят использовать пауки, так как тоже лишняя сущность и в minimal install их нет.

Вобщем автор, портировал этот скрипт на язык, присутствующий в любой unix-системе (/bin/sh) и добавил обработку jail-a. Сохраните код ниже в какой-нибудь ‘/usr/bin/free’, сделайте ему ‘chmod a+x’ и наслаждайтесь.

#!/bin/sh

mem_phys=`sysctl -n hw.physmem`
mem_pgs=`sysctl -n hw.pagesize`
sys_jail=`sysctl -n security.jail.jailed`

# guess hardware memory size
chip_size=1
chip_guess=`expr $mem_phys / 8 - 1`
while [ $chip_guess -ne 0 ]; do
        chip_guess=`expr $chip_guess / 2`
        chip_size=`expr $chip_size \* 2`
done
mem_hw=`expr \( $mem_phys - 1 \) / $chip_size`
mem_hw=`expr $mem_hw \* $chip_size + $chip_size`

# determine the individual known information
mem_all=`sysctl -n vm.stats.vm.v_page_count`
mem_all=`expr $mem_all \* $mem_pgs`
mem_wire=`sysctl -n vm.stats.vm.v_wire_count`
mem_wire=`expr $mem_wire \* $mem_pgs`
mem_active=`sysctl -n vm.stats.vm.v_active_count`
mem_active=`expr $mem_active \* $mem_pgs`
mem_inactive=`sysctl -n vm.stats.vm.v_inactive_count`
mem_inactive=`expr $mem_inactive \* $mem_pgs`
mem_cache=`sysctl -n vm.stats.vm.v_cache_count`
mem_cache=`expr $mem_cache \* $mem_pgs`
mem_free=`sysctl -n vm.stats.vm.v_free_count`
mem_free=`expr $mem_free \* $mem_pgs`

# determine the individual unknown information
mem_gap_vm=`expr -- $mem_all - \( $mem_wire + $mem_active + $mem_inactive + $mem_cache + $mem_free \)`
mem_gap_sys=`expr -- $mem_phys - $mem_all`
mem_gap_hw=`expr -- $mem_hw - $mem_phys`

# determine logical summary information
mem_total=$mem_hw
mem_avail=`expr -- $mem_inactive + $mem_cache + $mem_free`
mem_used=`expr -- $mem_total - $mem_avail`

# print system results
printf "System memory information (page size is %d bytes)\n" $mem_pgs
if [ $sys_jail -eq 1 ]; then
        printf "WE ARE IN THE JAIL\n"
        printf "mem_wire:      %12d (%7dMB) %s\n" $mem_wire `expr -- $mem_wire / 1048576` 'Wired: disabled for paging out'
        printf "mem_active:    %12d (%7dMB) %s\n" $mem_active `expr -- $mem_active / 1048576` 'Active: recently referenced'
        printf "mem_inactive:  %12d (%7dMB) %s\n" $mem_inactive `expr -- $mem_inactive / 1048576` 'Inactive: recently not referenced'
        printf "mem_cache:     %12d (%7dMB) %s\n" $mem_cache `expr -- $mem_cache / 1048576` 'Cached: almost avail. for allocation'
        printf "mem_free:      %12d (%7dMB) %s\n" $mem_free `expr -- $mem_free / 1048576` 'Free: fully available for allocation'
        printf -- "-------------- ------------ -----------\n"
        printf "mem_phys:      %12d (%7dMB) %s\n" $mem_phys `expr -- $mem_phys  / 1048576` 'Total real memory available'
else
        printf "mem_wire:      %12d (%7dMB) [%3d%%] %s\n" $mem_wire `expr -- $mem_wire / 1048576` `expr -- $mem_wire \* 100 / $mem_all` 'Wired: disabled for paging out'
        printf "mem_active:  + %12d (%7dMB) [%3d%%] %s\n" $mem_active `expr -- $mem_active / 1048576` `expr -- $mem_active \* 100 / $mem_all` 'Active: recently referenced'
        printf "mem_inactive:+ %12d (%7dMB) [%3d%%] %s\n" $mem_inactive `expr -- $mem_inactive / 1048576` `expr -- $mem_inactive \* 100 / $mem_all` 'Inactive: recently not referenced'
        printf "mem_cache:   + %12d (%7dMB) [%3d%%] %s\n" $mem_cache `expr -- $mem_cache / 1048576` `expr -- $mem_cache \* 100 / $mem_all` 'Cached: almost avail. for allocation'
        printf "mem_free:    + %12d (%7dMB) [%3d%%] %s\n" $mem_free `expr -- $mem_free / 1048576` `expr -- $mem_free \* 100 / $mem_all` 'Free: fully available for allocation'
        printf "mem_gap_vm:  + %12d (%7dMB) [%3d%%] %s\n" $mem_gap_vm `expr -- $mem_gap_vm / 1048576` `expr -- $mem_gap_vm  \* 100 / $mem_all` 'Memory gap: UNKNOWN'
        printf -- "-------------- ------------ ----------- ------\n"
        printf "mem_all:     = %12d (%7dMB) [100%%] %s\n" $mem_all `expr -- $mem_all / 1048576` 'Total real memory managed'
        printf "mem_gap_sys: + %12d (%7dMB)        %s\n" $mem_gap_sys `expr -- $mem_gap_sys / 1048576` 'Memory gap: Kernel?!'
        printf -- "-------------- ------------ -----------\n"
        printf "mem_phys:    = %12d (%7dMB)        %s\n" $mem_phys `expr -- $mem_phys / 1048576` 'Total real memory available'
        printf "mem_gap_hw:  + %12d (%7dMB)        %s\n" $mem_gap_hw `expr -- $mem_gap_hw / 1048576` 'Memory gap: Segment Mappings?!'
        printf -- "-------------- ------------ -----------\n"
        printf "mem_hw:      = %12d (%7dMB)        %s\n" $mem_hw `expr -- $mem_hw / 1048576` 'Total real memory installed'
fi

# print logical results
if [ $sys_jail -ne 1 ]; then
        printf "\nSystem memory summary\n"
        printf "mem_used:      %12d (%7dMB) [%3d%%] %s\n" $mem_used `expr -- $mem_used / 1048576` `expr -- $mem_used \* 100 / $mem_total` 'Logically used memory'
        printf "mem_avail:   + %12d (%7dMB) [%3d%%] %s\n" $mem_avail `expr -- $mem_avail / 1048576` `expr -- $mem_avail \* 100 / $mem_total` 'Logically available memory'
        printf -- "-------------- ------------ ----------- ------\n"
        printf "mem_total:   = %12d (%7dMB) [100%%] %s\n" $mem_total `expr -- $mem_total / 1048576` 'Logically total memory'
fi

Пример вывода:

System memory information (page size is 4096 bytes)
mem_wire:        1384239104 (   1320MB) [ 67%] Wired: disabled for paging out
mem_active:  +     19644416 (     18MB) [  0%] Active: recently referenced
mem_inactive:+      4112384 (      3MB) [  0%] Inactive: recently not referenced
mem_cache:   +        36864 (      0MB) [  0%] Cached: almost avail. for allocation
mem_free:    +    654012416 (    623MB) [ 31%] Free: fully available for allocation
mem_gap_vm:  +       512000 (      0MB) [  0%] Memory gap: UNKNOWN
-------------- ------------ ----------- ------
mem_all:     =   2062557184 (   1967MB) [100%] Total real memory managed
mem_gap_sys: +     63373312 (     60MB)        Memory gap: Kernel?!
-------------- ------------ -----------
mem_phys:    =   2125930496 (   2027MB)        Total real memory available
mem_gap_hw:  +     21553152 (     20MB)        Memory gap: Segment Mappings?!
-------------- ------------ -----------
mem_hw:      =   2147483648 (   2048MB)        Total real memory installed

System memory summary
mem_used:        1489321984 (   1420MB) [ 69%] Logically used memory
mem_avail:   +    658161664 (    627MB) [ 30%] Logically available memory
-------------- ------------ ----------- ------
mem_total:   =   2147483648 (   2048MB) [100%] Logically total memory