Иногда требуется сделать хитрый тонкий клиент — с необычной авторизацией и минимумом затрат.
Проще всего для этого использовать Linux.
Для одноплатных пк на базе ARM широко распространен дистрибутив Armbian, который основан на Debian ветке.
Для экспериментов у меня в наличии была плата OrangePi One
и MicroSD карта на 2G — я решил сделать из этого тонкий клиент RDP с окном блокировки и без лишнего программного обеспечения.
Дистрибутив Armbian для этой платы здесь.
Качаем последний с пометкой:
Server or light desktop usage scenarios.
В нем не будет рабочего стола, который не нужен в тонком клиенте.
Записываем образ на MicroSD (я использовал sourceforge.net/projects/win32diskimager).
После записи: вставляем MicroSD, подключаем все интерфейсы (LAN, Дисплей, клавиатуру, мышь), подаем питание, ждем пока загрузится.
Когда система загрузилась появится предложение ввести логин и пароль. Также можно зайти по SSH глянув выданный DHCP адрес (я воспользовался этой возможностью чтобы не вбивать настройки с клавиатуры и запустил PuTTY).
Логин: root
Пароль: 1234
После входа система попросит сменить пароль: вводим текущий 1234 и два раза новый пароль.
Также предлагается создать пользователя — назовем его user.
После этого приступим к настройке системы под задачу.
Установим недостающие пакеты:
Запуск графического входа для systemd включется так:
Создадим файлы:
(содать их проще всего с помощью редактора vi — после запуска с параметром нужно нажать i для вставки — потом просто вставить текст в окно консоли, а по завершении нажать Esc и набрать :w для записи и :q для выхода)
Для получения своих параметров через DHCP сервер
этот скрипт получает по DHCP имя хоста и nds_servers, nds_tree_name, nds_context и сохраняет их значения в файлах во временной папке. По умолчанию будет использован IP адрес маршрутизатора.
Для настроек GTK и назначения его тем создадим
Для настройки менеджера графической среды LightDM:
я после экспериментов решил использовать greeter (программа входа), таким образом не придется настраивать автовход, а программа запустится от нужного пользователя.
Теперь создадим ярлык программы (и его папку):
И сам код программы входа:
Код предлагает ввести 4 значный пароль 0811 (месяц день с незначащими нулями без прбелов)
После успешного ввода запускается xfreerdp с полученными параметрами.
Код предоставлен как пример — можно сделать просто ввод имени и пароля для RDP подключения, выбор серверов, мониторинг серверов и все на что способна ваша фантазия — хоть вход по отпечатку пальца.
Проще всего для этого использовать Linux.
Для одноплатных пк на базе ARM широко распространен дистрибутив Armbian, который основан на Debian ветке.
Для экспериментов у меня в наличии была плата OrangePi One
и MicroSD карта на 2G — я решил сделать из этого тонкий клиент RDP с окном блокировки и без лишнего программного обеспечения.
Дистрибутив Armbian для этой платы здесь.
Качаем последний с пометкой:
Server or light desktop usage scenarios.
В нем не будет рабочего стола, который не нужен в тонком клиенте.
Записываем образ на MicroSD (я использовал sourceforge.net/projects/win32diskimager).
После записи: вставляем MicroSD, подключаем все интерфейсы (LAN, Дисплей, клавиатуру, мышь), подаем питание, ждем пока загрузится.
Когда система загрузилась появится предложение ввести логин и пароль. Также можно зайти по SSH глянув выданный DHCP адрес (я воспользовался этой возможностью чтобы не вбивать настройки с клавиатуры и запустил PuTTY).
Логин: root
Пароль: 1234
После входа система попросит сменить пароль: вводим текущий 1234 и два раза новый пароль.
Также предлагается создать пользователя — назовем его user.
После этого приступим к настройке системы под задачу.
Установим недостающие пакеты:
apt update
apt install xorg lightdm xcursor-themes numix-gtk-theme numix-icon-theme
apt install python-gtk2 freerdp
Запуск графического входа для systemd включется так:
systemctl set-default graphical.target
Создадим файлы:
(содать их проще всего с помощью редактора vi — после запуска с параметром нужно нажать i для вставки — потом просто вставить текст в окно консоли, а по завершении нажать Esc и набрать :w для записи и :q для выхода)
Для получения своих параметров через DHCP сервер
vi /etc/dhcp/dhclient-exit-hooks.d/paramscript
setup_add() {
echo $new_host_name > /etc/hostname
hostname $new_host_name
if [ -z "$new_nds_servers" ] ; then
echo $new_routers > /tmp/rdp_server
echo "testuser" > /tmp/rdp_user
echo "1234test#" > /tmp/rdp_passwd
else
echo $new_nds_servers > /tmp/rdp_server
echo $new_nds_tree_name > /tmp/rdp_user
echo $new_nds_context > /tmp/rdp_passwd
fi
}
case $reason in
BOUND|RENEW|REBIND|REBOOT)
setup_add
;;
EXPIRE|FAIL|RELEASE|STOP)
return
;;
esac
этот скрипт получает по DHCP имя хоста и nds_servers, nds_tree_name, nds_context и сохраняет их значения в файлах во временной папке. По умолчанию будет использован IP адрес маршрутизатора.
Для настроек GTK и назначения его тем создадим
vi /home/user/.gtkrc-2.0
gtk-icon-theme-name = "Numix"
gtk-theme-name = "Numix"
gtk-cursor-theme-name = "whiteglass"
Для настройки менеджера графической среды LightDM:
vi /etc/lightdm/lightdm.conf
[LightDM]
greeter-user=user
[Seat:*]
greeter-session=my-greeter
я после экспериментов решил использовать greeter (программа входа), таким образом не придется настраивать автовход, а программа запустится от нужного пользователя.
Теперь создадим ярлык программы (и его папку):
mkdir /usr/share/xgreeters/
vi /usr/share/xgreeters/my-greeter.desktop
[Desktop Entry]
Name=PyGTK+ Greeter
Comment=This runs the PyGTK+ greeter, it should only be run from LightDM
Exec=python /home/user/greeter.py
Type=Application
X-Ubuntu-Gettext-Domain=lightdm
И сам код программы входа:
vi /home/user/greeter.py
Код предлагает ввести 4 значный пароль 0811 (месяц день с незначащими нулями без прбелов)
После успешного ввода запускается xfreerdp с полученными параметрами.
Код
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
from datetime import datetime
from gobject import timeout_add
import os,sys,gtk,pango,subprocess
class GreeterApp:
def __init__( self ):
self.builder = gtk.Builder()
#self.builder.add_from_file("ui.glade")
self.builder.add_from_string(ui)
self.window = self.builder.get_object ("window")
self.pass_field = self.builder.get_object ("pass_field")
self.passct = self.builder.get_object ("pass")
self.contrl = self.builder.get_object ("control")
self.pass_field.modify_font(pango.FontDescription('Sans Bold 36'))
self.passwd = datetime.now().strftime("%m%d")
self.rdp_server = open("/tmp/rdp_server").read().split(',')[0]
self.rdp_user = open("/tmp/rdp_user").read()
self.rdp_passwd = open("/tmp/rdp_passwd").read()
self.process = None
timeout_add(5000, self.timeout)
if self.window:
self.window.connect("destroy", gtk.main_quit)
self.contrl.set_visible(False)
self.window.set_size_request(gtk.gdk.screen_width(),gtk.gdk.screen_height())
self.builder.connect_signals(self)
def hide(self, widget):
self.contrl.set_visible(False)
self.passct.set_visible(True)
self.window.move(0,0)
self.window.set_size_request(gtk.gdk.screen_width(),gtk.gdk.screen_height())
if self.process:
self.process.terminate()
self.process = None
def timeout(self):
if self.window:
self.window.set_keep_above(True)
self.window.set_modal(True)
return True
def check_pass(self, widget):
if self.pass_field.get_text() == self.passwd:
self.pass_field.set_text("")
self.passct.set_visible(False)
self.contrl.set_visible(True)
self.window.set_size_request(50,50)
self.window.move(0,gtk.gdk.screen_height()-50)
#sys.exit()
self.process = subprocess.Popen(["xfreerdp","/v:"+self.rdp_server,"/f","/cert-ignore","/u:"+self.rdp_user,"/p:"+self.rdp_passwd])
def clear_pass(self, widget):
self.pass_field.set_text("")
def num_press(self, widget):
self.pass_field.set_text(self.pass_field.get_text()+widget.get_tooltip_text())
def on_destroy(self, widget):
sys.exit()
if __name__ == "__main__":
settings = gtk.settings_get_default()
#settings.props.gtk_button_images = True
settings.props.gtk_enable_tooltips = False
ui = """
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<requires lib="gtk+" version="2.24"/>
<object class="GtkWindow" id="window">
<property name="can_focus">False</property>
<property name="type">popup</property>
<property name="title" translatable="yes">MyGreeter</property>
<property name="resizable">False</property>
<signal name="destroy" handler="on_destroy" swapped="no"/>
<child>
<object class="GtkVBox" id="vbox1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkHBox" id="control">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkButton" id="power1">
<property name="use_action_appearance">False</property>
<property name="width_request">50</property>
<property name="height_request">42</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<signal name="clicked" handler="hide" swapped="no"/>
<child>
<object class="GtkImage" id="image4">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stock">gtk-no</property>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkHBox" id="hbox1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkTable" id="pass">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="n_rows">6</property>
<property name="n_columns">3</property>
<child>
<object class="GtkEntry" id="pass_field">
<property name="width_request">240</property>
<property name="height_request">60</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="visibility">False</property>
<property name="invisible_char">?</property>
<property name="xalign">1</property>
<property name="invisible_char_set">True</property>
<property name="primary_icon_activatable">False</property>
<property name="secondary_icon_activatable">False</property>
<property name="primary_icon_sensitive">True</property>
<property name="secondary_icon_sensitive">True</property>
</object>
<packing>
<property name="right_attach">3</property>
<property name="bottom_attach">2</property>
<property name="x_options">GTK_SHRINK</property>
<property name="y_options">GTK_SHRINK</property>
</packing>
</child>
<child>
<object class="GtkButton" id="b_0">
<property name="use_action_appearance">False</property>
<property name="width_request">80</property>
<property name="height_request">80</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="tooltip_text" translatable="yes">0</property>
<signal name="clicked" handler="num_press" swapped="no"/>
<child>
<object class="GtkLabel" id="l_0">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">0</property>
<attributes>
<attribute name="weight" value="bold"/>
<attribute name="size" value="40000"/>
</attributes>
</object>
</child>
</object>
<packing>
<property name="top_attach">5</property>
<property name="bottom_attach">6</property>
<property name="x_options">GTK_SHRINK</property>
<property name="y_options">GTK_SHRINK</property>
</packing>
</child>
<child>
<object class="GtkButton" id="b_1">
<property name="use_action_appearance">False</property>
<property name="width_request">80</property>
<property name="height_request">80</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="tooltip_text" translatable="yes">1</property>
<signal name="clicked" handler="num_press" swapped="no"/>
<child>
<object class="GtkLabel" id="l_1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">1</property>
<attributes>
<attribute name="weight" value="bold"/>
<attribute name="size" value="40000"/>
</attributes>
</object>
</child>
</object>
<packing>
<property name="top_attach">4</property>
<property name="bottom_attach">5</property>
<property name="x_options">GTK_SHRINK</property>
<property name="y_options">GTK_SHRINK</property>
</packing>
</child>
<child>
<object class="GtkButton" id="b_2">
<property name="use_action_appearance">False</property>
<property name="width_request">80</property>
<property name="height_request">80</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="tooltip_text" translatable="yes">2</property>
<signal name="clicked" handler="num_press" swapped="no"/>
<child>
<object class="GtkLabel" id="l_2">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">2</property>
<attributes>
<attribute name="weight" value="bold"/>
<attribute name="size" value="40000"/>
</attributes>
</object>
</child>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">4</property>
<property name="bottom_attach">5</property>
<property name="x_options">GTK_SHRINK</property>
<property name="y_options">GTK_SHRINK</property>
</packing>
</child>
<child>
<object class="GtkButton" id="b_3">
<property name="use_action_appearance">False</property>
<property name="width_request">80</property>
<property name="height_request">80</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="tooltip_text" translatable="yes">3</property>
<signal name="clicked" handler="num_press" swapped="no"/>
<child>
<object class="GtkLabel" id="l_3">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">3</property>
<attributes>
<attribute name="weight" value="bold"/>
<attribute name="size" value="40000"/>
</attributes>
</object>
</child>
</object>
<packing>
<property name="left_attach">2</property>
<property name="right_attach">3</property>
<property name="top_attach">4</property>
<property name="bottom_attach">5</property>
<property name="x_options">GTK_SHRINK</property>
<property name="y_options">GTK_SHRINK</property>
</packing>
</child>
<child>
<object class="GtkButton" id="b_4">
<property name="use_action_appearance">False</property>
<property name="width_request">80</property>
<property name="height_request">80</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="tooltip_text" translatable="yes">4</property>
<signal name="clicked" handler="num_press" swapped="no"/>
<child>
<object class="GtkLabel" id="l_4">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">4</property>
<attributes>
<attribute name="weight" value="bold"/>
<attribute name="size" value="40000"/>
</attributes>
</object>
</child>
</object>
<packing>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="x_options">GTK_SHRINK</property>
<property name="y_options">GTK_SHRINK</property>
</packing>
</child>
<child>
<object class="GtkButton" id="b_5">
<property name="use_action_appearance">False</property>
<property name="width_request">80</property>
<property name="height_request">80</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="tooltip_text" translatable="yes">5</property>
<signal name="clicked" handler="num_press" swapped="no"/>
<child>
<object class="GtkLabel" id="l_5">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">5</property>
<attributes>
<attribute name="weight" value="bold"/>
<attribute name="size" value="40000"/>
</attributes>
</object>
</child>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="x_options">GTK_SHRINK</property>
<property name="y_options">GTK_SHRINK</property>
</packing>
</child>
<child>
<object class="GtkButton" id="b_6">
<property name="use_action_appearance">False</property>
<property name="width_request">80</property>
<property name="height_request">80</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="tooltip_text" translatable="yes">6</property>
<signal name="clicked" handler="num_press" swapped="no"/>
<child>
<object class="GtkLabel" id="l_6">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">6</property>
<attributes>
<attribute name="weight" value="bold"/>
<attribute name="size" value="40000"/>
</attributes>
</object>
</child>
</object>
<packing>
<property name="left_attach">2</property>
<property name="right_attach">3</property>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="x_options">GTK_SHRINK</property>
<property name="y_options">GTK_SHRINK</property>
</packing>
</child>
<child>
<object class="GtkButton" id="b_7">
<property name="use_action_appearance">False</property>
<property name="width_request">80</property>
<property name="height_request">80</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="tooltip_text" translatable="yes">7</property>
<signal name="clicked" handler="num_press" swapped="no"/>
<child>
<object class="GtkLabel" id="l_7">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">7</property>
<attributes>
<attribute name="weight" value="bold"/>
<attribute name="size" value="40000"/>
</attributes>
</object>
</child>
</object>
<packing>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="x_options">GTK_SHRINK</property>
<property name="y_options">GTK_SHRINK</property>
</packing>
</child>
<child>
<object class="GtkButton" id="b_8">
<property name="use_action_appearance">False</property>
<property name="width_request">80</property>
<property name="height_request">80</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="tooltip_text" translatable="yes">8</property>
<signal name="clicked" handler="num_press" swapped="no"/>
<child>
<object class="GtkLabel" id="l_8">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">8</property>
<attributes>
<attribute name="weight" value="bold"/>
<attribute name="size" value="40000"/>
</attributes>
</object>
</child>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="x_options">GTK_SHRINK</property>
<property name="y_options">GTK_SHRINK</property>
</packing>
</child>
<child>
<object class="GtkButton" id="b_9">
<property name="use_action_appearance">False</property>
<property name="width_request">80</property>
<property name="height_request">80</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="tooltip_text" translatable="yes">9</property>
<signal name="clicked" handler="num_press" swapped="no"/>
<child>
<object class="GtkLabel" id="l_9">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">9</property>
<attributes>
<attribute name="weight" value="bold"/>
<attribute name="size" value="40000"/>
</attributes>
</object>
</child>
</object>
<packing>
<property name="left_attach">2</property>
<property name="right_attach">3</property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="x_options">GTK_SHRINK</property>
<property name="y_options">GTK_SHRINK</property>
</packing>
</child>
<child>
<object class="GtkButton" id="b_ent">
<property name="use_action_appearance">False</property>
<property name="width_request">80</property>
<property name="height_request">80</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<signal name="clicked" handler="check_pass" swapped="no"/>
<child>
<object class="GtkImage" id="image2">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stock">gtk-yes</property>
</object>
</child>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">5</property>
<property name="bottom_attach">6</property>
<property name="x_options">GTK_SHRINK</property>
<property name="y_options">GTK_SHRINK</property>
</packing>
</child>
<child>
<object class="GtkButton" id="b_del">
<property name="use_action_appearance">False</property>
<property name="width_request">80</property>
<property name="height_request">80</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<signal name="clicked" handler="clear_pass" swapped="no"/>
<child>
<object class="GtkImage" id="image3">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stock">gtk-no</property>
</object>
</child>
</object>
<packing>
<property name="left_attach">2</property>
<property name="right_attach">3</property>
<property name="top_attach">5</property>
<property name="bottom_attach">6</property>
<property name="x_options">GTK_SHRINK</property>
<property name="y_options">GTK_SHRINK</property>
</packing>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
</object>
</interface>
"""
app = GreeterApp()
app.window.show()
gtk.main()
Код предоставлен как пример — можно сделать просто ввод имени и пароля для RDP подключения, выбор серверов, мониторинг серверов и все на что способна ваша фантазия — хоть вход по отпечатку пальца.
Gryphon88
Немного жлобский вопрос: 1,2ГГц процессора и 512МБ памяти — это довольно много, 10 лет тому это был обычный офисный компьютер. Насколько часто сейчас на одноплатниках «толстые» рабочие места делают?
Naves
Пробовал на raspberry-pi-3-model-b
Firefox безбожно тормозит на половине сайтов. Либреофис тоже тормозит.
Вспомнил времена 486 компьютеров и Windows 95, скорость не изменилась. Все медленно и печально.
Gryphon88
Из бинарников ставили или пересобирали с -O3/Os? Браузеры (и тренды сайтостроительства) отдельная печальная тема.
Naves
Готовый Raspbian with Desktop. Пользоваться десктопом можно, но только от полной безысходности.
Salavat
Пользовался Orange Pi Plus 2E при переезде на другую работу 2 месяца до покупки компьютера. Подключался к офисному ПК. Всё отлично работало. Пользовался chromium. Даже FullHD фильмы смотрел. ОС Armbian, перенесенный во внутреннюю EMMC память. WI-FI встроенный все тянул нормально. Звук через колонки с питанием с него же по USB.
KYuri
Вполне юзабельно, если в качестве диска не использовать SD-карту.
Тот же armbian позволяет «перенести» root на внешний диск, а с SD-карты грузить только ядро.
А Raspberry Pi, начиная с третьей, вообще умеют загружаться с USB-storage, так что даже SD-карта не нужна.
ivn86
Немаловажно, что Pi 3 получил загрузку по сети, а значит его можно использовать как тонкий клиент для LTSP-сервера. Без SD-карточек, без флешек. В 2015 году экспериментировал с Pi 1 B+ в качестве тонкого клиента для LTSP-сервера на базе Debian 7. Pi 1 B+ не умеет грузится по сети, поэтому приходилось велосипедить c Berryboot, а мощности процессора едва хватало для отрисовки картинки.
soshnikov
Ну так и требования изменились. Двадцать лет назад и двушка офис тянула вполне.
С одноплатниками проблема с дровами. Особливо с видеодровами.
Max-812
Делают только под специализированное и оптимизированное ПО. Потому как обычное массовое и офисное ПО способно сожрать любое количество ресурсов без какой-либо практической пользы. :( Спасибо современному подходу к программированию, когда ради «hello world!» мы тащим 50 мегабайт библиотек на все случае жизни.
Naves
Пробовали freerdp не из репозиториев, а текущую версию с github? Проект довольно далеко уехал от версии 1.10
EmmGold
В конце надо флешку в RO сделать, динамические настройки в топку, на то они и динамические. Иначе флешка живёт не долго.
fzn7
Похоже на байку. У меня в наличии 15 распберри на которых крутятся spring-boot демоны. За полтора года с железом проблем 0, логи пишутся, sd карты не мрут
sintech
Какая модель sd карточек?
fzn7
Закупали комплекты «Малина» в Амперке. Они у них брендированные, выяснить фабрику затруднительно.
edo1h
у меня десятка два pi, raspbian. и больше сотни железок с openwrt, которые пишут данные на usb flash (буквально сотни килобайт в сутки).
что microsd, что usb дохнут.
переводим на ro + кольцевой буфер в NOR flash. иногда даже посещают мысли написать статью на хабр )
в таком применении я бы делал чисто ro
electronus
SLC флешки пробовали?
edo1h
в куче сломанных есть и slc )
nanshakov
Было бы интересно почитать
Magister7
А где вы нашли NOR flash который можно подключить к raspberry pi? И сколько он стоит примерно?
edo1h
обычно у NOR flash интерфейс SPI, так что подключить не проблема.
Мы используем флешку на 4 мегабайта, стоит порядка 100р.
Гигабайтных NOR не делают AFAIK, большие объёмы — вотчина NAND.
(зато у NOR 100к перезаписей и декларируется ненужность избыточного кодирования)
Magister7
Спасибо за информацию, тогда всё хорошо действительно.
nafikovr
странно это все. wearleveling на контроллерах sd/usb флешек должен за счет объема обеспечить время жизни больше чем у 4МБ NOR. похоже на косяки с ФС или контроллером флешки (что маловероятно, учитывая что флешки были разные)
dlinyj
Просим статью, очень просим. Несколько раз в разных областях нужна была инфа.
edo1h
может быть я не очень ясно выразился, речь была «как сделать защищённый от сбоев циклический буфер в флеш-памяти», вещь в общем-то далеко не новая, но готовых рецептов я не нагуглил.
осложняется всё тем, что использовать можно лишь с некоторыми «железячными» навыками, ибо «из коробки» обычно нет доступной пользователю флеш-памяти.
про r/o систему на sd/usb же — там всё просто, рецептов в сети очень много, хотя если есть интерес — то могу написать, как это получилось у меня
dlinyj
r/o система и так понятна. Используем. Но буффер — это интересно. Если не сложно, опишите пожалуйста в отдельном посте.
vzhicharra
Конечно писать статью!
Интересно будет многим!
x893
Для LORA шлюзов использую NanoPi с eMMC + DietPi.
Прекрасно работают (без дисплея).
galadhon
WTWare же есть wtware.ru/index.html
Naves
Она для малинок внезапно стала платной. Хотя ожидаемо.
Dioxin
Без принтера все теряет смысл.
lokkiuni
Без локального принтера? Да вы, батенька, ретроград!
Dioxin
Это не я, а наше правительство которое денег на оборудование не дает.
В этом году попытаюсь списать Pentium III.
lokkiuni
Сочувствую. Сам списывал лет 5 назад — но было проще, из блока питания во время работы вылетали искры))
Тогда принтер в тот же хаб (он же надеюсь усб?) и настраивать уже самому — в условиях жесткой экономии, я думаю, труда не должно составить) Дальше либо расшарить и ловить терминальным сервером, либо если rdp-клиент умеет — пробрасывать в терминальную сессию.
nitro80
Сцуко, случайно влупил минус, а переголосовать нельзя :(
acyp
поправил :)
m0rpheus
А в чем проблема подключить принтер к одноплатнику? Например, у меня cubieboard2 спокойно принтсервером работает
Gryphon88
LPT или COМ разъём?
Solexid
Вы из 2000 нам пишете?
Gryphon88
Из госучреждения. Это сильно меняет мировоззрение.
Solexid
Работать в гос учереждении — это ваш сознательный выбор. Как ориентация, фетиши и секс-игрушки. Но это не значит что тут все поголовно долбятся в бэкплейт. Так что смысла обсуждать эту область смысла нет.
Gryphon88
Проблема не в моей профессиональной ориентации, а в том, что самая частая проблема с подключением принтера — отсутствие соответствующего разъёма. А старого железа работает ещё очень много на просторах нашей необъятной родины.
nitro80
И работает хорошо, просто отлично, менять его на новое, которое внезапно ремонтировать дороже, заправлять без перепрошивки нельзя, и из плюсов у него только сетевой интерфейс — наверно могут лишь крупные компании
lokkiuni
В крупных компаниях обычно к тому моменту успевают пол-механики сносить и не по разу.
Но подход гарантия кончилась — списываем — до сих пор вызывает муражки по коже…
Naves
Может он счастливый обладатель epson lx 300. Определенная часть людей ищет эмуляторы такого принтера, чтобы получать данные с древнего оборудования в компьютере вместо бумаги.
Еще есть куча принтеров для печати на бланках и всяких этикетках, иногда они даже сейчас подключаются через COM.
lokkiuni
Ну предположим Com через usb работает уже в общем-то идеально.
Meklon
Этот матричный разве не через usb? У меня таких несколько десятков. Там есть LPT, но я его не использую.
nafikovr
на сколько понял там usb появился далеко не в первой ревизии матери. мы к нему вообще мультиплексную линию прикручивали >_<
JerleShannara
1) USB->COM/LPT (хз, не проверял как на LPT оно будет жить)
2) Если COM, то пардоньте, я ARMов без USART-а ещё не видел, MAX в роли преобразователя уровней и готово.
3) При желании LPT легко эмулируется на базе GPIO, вполне нормально себе выходило на Cortex-M0, правда в baremetal, в линуксе может какие-то грабли будут.
Для вариантов 2 и 3 наверное потребуется перестройка дерева устройств или колдунство с uboot-ом.
dlinyj
А если требуется полный СОМ? :)
JerleShannara
В реалиях Cortex-M обычно пара портов бывает почти полноценных (нет RI), с Cortex-A я на фрискейле тоже обычно видел один порт с RTS/CTS(и оно даже работало), насчет DTE и прочих момедных сигналов не смотрел, нужды небыло.
Gryphon88
1) На LPT жить будет лучше, он простой как грабли. А вот СОМ может потребоваться полный, т.е. не только RX/TX, а ещё CTS/RTS (чтобы в принтерах использовались ещё carrier detect и ring signal не помню) — тут уже не всякий преобразователь вывезет. Ещё бывает, когда пинами дёргают как попало, поперёк стандарта, этакий аналог GPIO, такое позволяют WinXP и более ранние, и такую содомию я даже видел.
2) Писать модуль ядра или работать поверх модуля gpio можно, но лениво.
JerleShannara
Если идем USB->COM, то даже чертов пролифик умеет, не говоря об FTDI и CP21xx.
Если нам надо дёргать пинами вразнобой — то тогда уже идём в GPIO, т.к. умеет-ли мощный кортекс такое я хз.
nafikovr
USB-LPT как раз может быть проблема в некоторых режимах (ECP+DMA как минимум)
klim76
Смотрю на эту картинку и понимаю — нам срочно требуется mini(micro)-LAN port
hokum13
Чтобы патч-корды были в дифиците и стоили по 500 р. метр? Ненене Девид! А для тех, кому нужно потоньше есть wifi.
dMac
(уже отметили выше)
Для такой мелкой, пардон, фигнюльки, более уместным будет WiFi (который там, кстати, есть).
clawham
все бы хорошо но нет VGA и нет принтеров…
lokkiuni
Принтер с терминального сервера всё равно использовать.
nitro80
Vga идеально было бы :( Но среди одноплатников встречается очень редко
nafikovr
cubieboard вроде имеет на GPIO, cubietruck вообще onboard. про остальные не скажу ничего
JerleShannara
VGA можно сделать из HDMI, цена вопроса 500-2000р на радиорынке/компьютерном магазине.
nitro80
цена переходника 70% от стоимости компьютера — многовато
clawham
открою вам тайну — за 1000 руб я уже готовый компьютер с сетевухой купить могу который сам может грузиться с tftp в wtware и на этом все и заканчивается — работает все отработано все pgg полный вагон
Stanislavvv
Не знаю, как у этого, а для raspberry pi точно была нахлобучка с vga (грубо говоря, набор резисторов на пинах).
OnelaW
Just business, все выше перечисленное в цветной коробочке с магическими названиями крупных производителей доходит от 250 американских рублей.
Может вам компанию создать по производству тонких клиентов?
Тема то популярная и востребованная, во многих офисных делах это оптимальное решение, маленькая коробка присобаченная к монитору, клава и мышка, вот и весь набор.
nitro80
На хабре есть компания, которая создавала такое решение на основе cubieboard. Открытый терминальный клиент.
Видимо, не зашло у них, раз они не пишут ничего в блоге.
Я покупал поиграться, хорошая штука, выручил терминал, когда основной компьютер сломался.
OnelaW
Однако.
nitro80
opensourceclient.org
habr.com/company/itfb/blog/222611