Создание тонкого клиента на базе дешевых одноплатных ПК

Иногда требуется сделать хитрый тонкий клиент — с необычной авторизацией и минимумом затрат.

Проще всего для этого использовать Linux.

Для одноплатных пк на базе ARM широко распространен дистрибутив Armbian, который основан на Debian ветке.

Для экспериментов у меня в наличии была плата OrangePi One
image
и 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 подключения, выбор серверов, мониторинг серверов и все на что способна ваша фантазия — хоть вход по отпечатку пальца.
Поделиться публикацией
Комментарии 77
    0
    Немного жлобский вопрос: 1,2ГГц процессора и 512МБ памяти — это довольно много, 10 лет тому это был обычный офисный компьютер. Насколько часто сейчас на одноплатниках «толстые» рабочие места делают?
      +2
      Пробовал на raspberry-pi-3-model-b
      Firefox безбожно тормозит на половине сайтов. Либреофис тоже тормозит.
      Вспомнил времена 486 компьютеров и Windows 95, скорость не изменилась. Все медленно и печально.
        0
        Из бинарников ставили или пересобирали с -O3/Os? Браузеры (и тренды сайтостроительства) отдельная печальная тема.
          +2
          Готовый Raspbian with Desktop. Пользоваться десктопом можно, но только от полной безысходности.
          0

          Пользовался Orange Pi Plus 2E при переезде на другую работу 2 месяца до покупки компьютера. Подключался к офисному ПК. Всё отлично работало. Пользовался chromium. Даже FullHD фильмы смотрел. ОС Armbian, перенесенный во внутреннюю EMMC память. WI-FI встроенный все тянул нормально. Звук через колонки с питанием с него же по USB.


          Фото Orange Pi Plus 2E

          image


          Сейчас стоит на нем андроид + приложение HD VideoBox и висит над телевизором. Детям мультики смотреть самое то. Также ОС перенесена во внутреннюю память.


          Одно но: пассивный радиатор обязателен.

          +2
          Вполне юзабельно, если в качестве диска не использовать SD-карту.
          Тот же armbian позволяет «перенести» root на внешний диск, а с SD-карты грузить только ядро.
          А Raspberry Pi, начиная с третьей, вообще умеют загружаться с USB-storage, так что даже SD-карта не нужна.
            +1
            Raspberry Pi, начиная с третьей, вообще умеют загружаться с USB-storage

            Немаловажно, что Pi 3 получил загрузку по сети, а значит его можно использовать как тонкий клиент для LTSP-сервера. Без SD-карточек, без флешек. В 2015 году экспериментировал с Pi 1 B+ в качестве тонкого клиента для LTSP-сервера на базе Debian 7. Pi 1 B+ не умеет грузится по сети, поэтому приходилось велосипедить c Berryboot, а мощности процессора едва хватало для отрисовки картинки.
            0

            Ну так и требования изменились. Двадцать лет назад и двушка офис тянула вполне.
            С одноплатниками проблема с дровами. Особливо с видеодровами.

              +1
              Делают только под специализированное и оптимизированное ПО. Потому как обычное массовое и офисное ПО способно сожрать любое количество ресурсов без какой-либо практической пользы. :( Спасибо современному подходу к программированию, когда ради «hello world!» мы тащим 50 мегабайт библиотек на все случае жизни.
              0
              Пробовали freerdp не из репозиториев, а текущую версию с github? Проект довольно далеко уехал от версии 1.10
                0
                В конце надо флешку в RO сделать, динамические настройки в топку, на то они и динамические. Иначе флешка живёт не долго.
                  0
                  Похоже на байку. У меня в наличии 15 распберри на которых крутятся spring-boot демоны. За полтора года с железом проблем 0, логи пишутся, sd карты не мрут
                    0
                    Какая модель sd карточек?
                      0
                      Закупали комплекты «Малина» в Амперке. Они у них брендированные, выяснить фабрику затруднительно.
                      +3
                      у меня десятка два pi, raspbian. и больше сотни железок с openwrt, которые пишут данные на usb flash (буквально сотни килобайт в сутки).
                      что microsd, что usb дохнут.

                      переводим на ro + кольцевой буфер в NOR flash. иногда даже посещают мысли написать статью на хабр )
                      в таком применении я бы делал чисто ro
                        0
                        SLC флешки пробовали?
                          0
                          в куче сломанных есть и slc )
                          0
                          Было бы интересно почитать
                            0
                            А где вы нашли NOR flash который можно подключить к raspberry pi? И сколько он стоит примерно?
                              +2
                              обычно у NOR flash интерфейс SPI, так что подключить не проблема.
                              Мы используем флешку на 4 мегабайта, стоит порядка 100р.
                              Гигабайтных NOR не делают AFAIK, большие объёмы — вотчина NAND.
                              (зато у NOR 100к перезаписей и декларируется ненужность избыточного кодирования)
                                0
                                Спасибо за информацию, тогда всё хорошо действительно.
                                  0
                                  странно это все. wearleveling на контроллерах sd/usb флешек должен за счет объема обеспечить время жизни больше чем у 4МБ NOR. похоже на косяки с ФС или контроллером флешки (что маловероятно, учитывая что флешки были разные)
                                +3
                                Просим статью, очень просим. Несколько раз в разных областях нужна была инфа.
                                  +1
                                  может быть я не очень ясно выразился, речь была «как сделать защищённый от сбоев циклический буфер в флеш-памяти», вещь в общем-то далеко не новая, но готовых рецептов я не нагуглил.
                                  осложняется всё тем, что использовать можно лишь с некоторыми «железячными» навыками, ибо «из коробки» обычно нет доступной пользователю флеш-памяти.

                                  про r/o систему на sd/usb же — там всё просто, рецептов в сети очень много, хотя если есть интерес — то могу написать, как это получилось у меня
                                    0
                                    r/o система и так понятна. Используем. Но буффер — это интересно. Если не сложно, опишите пожалуйста в отдельном посте.
                                  0
                                  Конечно писать статью!
                                  Интересно будет многим!
                              0
                              Для LORA шлюзов использую NanoPi с eMMC + DietPi.
                              Прекрасно работают (без дисплея).
                                +1
                                WTWare же есть wtware.ru/index.html
                                  0
                                  Она для малинок внезапно стала платной. Хотя ожидаемо.
                                    0
                                    Если вся её платность сводится к появление надписи «Только для тестирования», то в чём проблема? У меня в своё время, когда я был сисадмином в отделе образования, лет пять крутилось около 30 таких машин.
                                  0
                                  Без принтера все теряет смысл.
                                    0
                                    Без локального принтера? Да вы, батенька, ретроград!
                                      +2
                                      Это не я, а наше правительство которое денег на оборудование не дает.
                                      В этом году попытаюсь списать Pentium III.
                                        0
                                        Сочувствую. Сам списывал лет 5 назад — но было проще, из блока питания во время работы вылетали искры))

                                        Тогда принтер в тот же хаб (он же надеюсь усб?) и настраивать уже самому — в условиях жесткой экономии, я думаю, труда не должно составить) Дальше либо расшарить и ловить терминальным сервером, либо если rdp-клиент умеет — пробрасывать в терминальную сессию.
                                          0

                                          Сцуко, случайно влупил минус, а переголосовать нельзя :(

                                            +3
                                            поправил :)
                                            0
                                            >> В этом году попытаюсь списать Pentium III.
                                            тогда можно использовать старый билд WTWare — и будет вам из Пня прекрасный тонкий клиент.
                                            Помню, у меня самый старый клиент был ПеньММХ с 2МБ ОЗУ — WTWare после загрузки по сети минуты три показывала чёрный экран пока процессор всё нужное обрабатывал. Зато потом всё летало как надо ;-)
                                          0

                                          А в чем проблема подключить принтер к одноплатнику? Например, у меня cubieboard2 спокойно принтсервером работает

                                            0
                                            LPT или COМ разъём?
                                              +2
                                              Вы из 2000 нам пишете?
                                                +1
                                                Из госучреждения. Это сильно меняет мировоззрение.
                                                  –3
                                                  Работать в гос учереждении — это ваш сознательный выбор. Как ориентация, фетиши и секс-игрушки. Но это не значит что тут все поголовно долбятся в бэкплейт. Так что смысла обсуждать эту область смысла нет.
                                                    +3
                                                    Проблема не в моей профессиональной ориентации, а в том, что самая частая проблема с подключением принтера — отсутствие соответствующего разъёма. А старого железа работает ещё очень много на просторах нашей необъятной родины.
                                                      +1

                                                      И работает хорошо, просто отлично, менять его на новое, которое внезапно ремонтировать дороже, заправлять без перепрошивки нельзя, и из плюсов у него только сетевой интерфейс — наверно могут лишь крупные компании

                                                        0
                                                        В крупных компаниях обычно к тому моменту успевают пол-механики сносить и не по разу.

                                                        Но подход гарантия кончилась — списываем — до сих пор вызывает муражки по коже…
                                                      0
                                                      кстати, ориентация- это не выбор.
                                                      0
                                                      >> Из госучреждения
                                                      >> LPT или COМ разъём
                                                      LPT без проблем перенаправляется как сетевой принтер, если правильно расшарить его. Причём можно даже расшарив подключать на этот самый компьютер — иногда по-другому в Win-среде использовать его не получается.
                                                      Самая «глубина» у меня в госучреждениях была — сделал сервер терминалов для DOS-овского 16-битного приложения (FoxPro 2.x) дя тонких клиентов, к каждому из которых был подключен LPT-принтер. Так что ничего невозможного нет.
                                                      +1
                                                      Может он счастливый обладатель epson lx 300. Определенная часть людей ищет эмуляторы такого принтера, чтобы получать данные с древнего оборудования в компьютере вместо бумаги.
                                                      Еще есть куча принтеров для печати на бланках и всяких этикетках, иногда они даже сейчас подключаются через COM.
                                                        +2
                                                        Ну предположим Com через usb работает уже в общем-то идеально.
                                                          0
                                                          >> Ну предположим Com через usb работает уже в общем-то идеально.
                                                          Далеко не всегда — как-то пробовал использовать такие переходники, ни разу не завелось. С DosPrn как-то проблем куда меньше.
                                                          0
                                                          Этот матричный разве не через usb? У меня таких несколько десятков. Там есть LPT, но я его не использую.
                                                            0
                                                            на сколько понял там usb появился далеко не в первой ревизии матери. мы к нему вообще мультиплексную линию прикручивали >_<
                                                              0
                                                              Lx300 lpt/com
                                                              Lx300+II USB/lpt/com
                                                              Lx350 полный аналог lx300(+II) по механике (спасибо эпсону что не стали поганить), также все интерфейсы скопом но зачем-то их перенесли с задней стенки в днище принтера, ближе к передней панели (иногда кабель коротковатым оказывается), дизайн посовременнее :)

                                                              Юзаю lx3xx полных ходом в сфере пассажирских перевозок, зверь машина :)
                                                        0
                                                        1) USB->COM/LPT (хз, не проверял как на LPT оно будет жить)
                                                        2) Если COM, то пардоньте, я ARMов без USART-а ещё не видел, MAX в роли преобразователя уровней и готово.
                                                        3) При желании LPT легко эмулируется на базе GPIO, вполне нормально себе выходило на Cortex-M0, правда в baremetal, в линуксе может какие-то грабли будут.

                                                        Для вариантов 2 и 3 наверное потребуется перестройка дерева устройств или колдунство с uboot-ом.
                                                          0
                                                          А если требуется полный СОМ? :)
                                                            0
                                                            В реалиях Cortex-M обычно пара портов бывает почти полноценных (нет RI), с Cortex-A я на фрискейле тоже обычно видел один порт с RTS/CTS(и оно даже работало), насчет DTE и прочих момедных сигналов не смотрел, нужды небыло.
                                                            0
                                                            1) На LPT жить будет лучше, он простой как грабли. А вот СОМ может потребоваться полный, т.е. не только RX/TX, а ещё CTS/RTS (чтобы в принтерах использовались ещё carrier detect и ring signal не помню) — тут уже не всякий преобразователь вывезет. Ещё бывает, когда пинами дёргают как попало, поперёк стандарта, этакий аналог GPIO, такое позволяют WinXP и более ранние, и такую содомию я даже видел.
                                                            2) Писать модуль ядра или работать поверх модуля gpio можно, но лениво.
                                                              0
                                                              Если идем USB->COM, то даже чертов пролифик умеет, не говоря об FTDI и CP21xx.
                                                              Если нам надо дёргать пинами вразнобой — то тогда уже идём в GPIO, т.к. умеет-ли мощный кортекс такое я хз.
                                                                0
                                                                У профилика большие проблемы с чётностью и двумя стопбитами.
                                                                0
                                                                USB-LPT как раз может быть проблема в некоторых режимах (ECP+DMA как минимум)
                                                                  0
                                                                  Нафига для LX-800 оно надо, сиё чудо и в SPP прекрасно живет
                                                                    0
                                                                    я к тому что не такой уж он и простой
                                                        +1
                                                        Смотрю на эту картинку и понимаю — нам срочно требуется mini(micro)-LAN port
                                                          +1
                                                          Чтобы патч-корды были в дифиците и стоили по 500 р. метр? Ненене Девид! А для тех, кому нужно потоньше есть wifi.
                                                            0
                                                            (уже отметили выше)
                                                            Для такой мелкой, пардон, фигнюльки, более уместным будет WiFi (который там, кстати, есть).
                                                            0
                                                            все бы хорошо но нет VGA и нет принтеров…
                                                              0
                                                              Принтер с терминального сервера всё равно использовать.
                                                                0

                                                                Vga идеально было бы :( Но среди одноплатников встречается очень редко

                                                                  0
                                                                  cubieboard вроде имеет на GPIO, cubietruck вообще onboard. про остальные не скажу ничего
                                                                  0
                                                                  VGA можно сделать из HDMI, цена вопроса 500-2000р на радиорынке/компьютерном магазине.
                                                                    0
                                                                    цена переходника 70% от стоимости компьютера — многовато
                                                                      +1
                                                                      открою вам тайну — за 1000 руб я уже готовый компьютер с сетевухой купить могу который сам может грузиться с tftp в wtware и на этом все и заканчивается — работает все отработано все pgg полный вагон
                                                                      0
                                                                      Не знаю, как у этого, а для raspberry pi точно была нахлобучка с vga (грубо говоря, набор резисторов на пинах).
                                                                      0
                                                                      Just business, все выше перечисленное в цветной коробочке с магическими названиями крупных производителей доходит от 250 американских рублей.

                                                                      Может вам компанию создать по производству тонких клиентов?
                                                                      Тема то популярная и востребованная, во многих офисных делах это оптимальное решение, маленькая коробка присобаченная к монитору, клава и мышка, вот и весь набор.
                                                                        0

                                                                        На хабре есть компания, которая создавала такое решение на основе cubieboard. Открытый терминальный клиент.
                                                                        Видимо, не зашло у них, раз они не пишут ничего в блоге.


                                                                        Я покупал поиграться, хорошая штука, выручил терминал, когда основной компьютер сломался.

                                                                          0
                                                                          Однако.

                                                                        Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                                                                        Самое читаемое