«Node.js» и «Тонкий клиент или создаем PXE Boot из LTSP»: разница между страницами

Материал из support.qbpro.ru
(Различия между страницами)
imported>Vix
 
imported>Vix
Нет описания правки
 
Строка 1: Строка 1:
process.nextTick(callback) - Гарантированно вызовет функцию callback в следующем цикле eventloop
'''ПОЭТАПНОЕ РУКОВОДСТВО ПО УСТАНОВКЕ И НАСТРОЙКЕ ТОНКОГО КЛИЕНТА НА ПЛАТФОРМЕ Linux Debian Squeeze '''


==Серверный JavaScript==
*И так, собрав в кучу все имеющееся руководство по настройке "тонкого" клиента и перебрав всевозможные
[[Руководство NodeJS]]
варианты и решения, рассмотрим задачу по созданию универсального образа или точнее платформы, на которой
[[Node.js Virtual Machine (vm) Usage (перевод)]]
можно создавать те или иные решения, с применением безопасных технологий.
===Node.JS Parent Process ID===
*Применительно к ситуации, создадим "тонкого" клиента, с возможностью обслуживания разделов жесткого диска,
Is it possible to get the parent process-id using Node.JS? I would like to detect if the parent is killed or fails in such a way that it cannot notify the child. If this happens, the parent process id of the child should become 1.
в частности с возможностью сохранения или восстановления образов партиций NTFS по сети.
*'''Далее по порядку''':
1. Устанавливаем необходимые пакеты:
apt-get install isc-dhcp-server tftpd-hpa ltsp-server nfs-common nfs-kernel-server


This would be preferable to requiring the parent to periodically send a keep-alive signal and also preferable to running the ps command.
* рекомендуется после установки запустить программу aptitude и до установить требуемые пакеты, если есть такой запрос...
@Emmerman: I'm not sure what you mean. The parent runs require('child_process').spawn(process.argv[0], ['path_to_child.js']) in order to start the child. Then if it needs to talk to the child, it uses the stdin and stdout of the child. stderr is piped to a log. I am guessing the answer would be yes?
* при установке сервера tftpd-hpa он будет просить вас указать каталог где будет "платформа", согласитесь по умолчанию /srv/tftp или /opt/ltsp, все равно потом это будем менять..


*You can use pid-file. Something like that
2. '''Теперь настраиваем сервер DHCP''':
*предположим что наша сеть такая:
root@debvbox:~#cat /etc/network/interfaces


  <nowiki>var util = require('util'),
  # The loopback network interface
    fs = require('fs'),
auto lo
    pidfile = '/var/run/nodemaster.pid';
iface lo inet loopback
# The primary network interface
auto eth0
iface eth0 inet static
        address 10.10.5.1
        netmask 255.255.255.0
        network 10.10.5.0
        broadcast 10.10.5.255
        gateway 10.10.5.1
        dns-nameservers 10.10.5.1


try {
*Исходя из этих данных настраиваем наш dhcp сервер:
    var pid = fs.readFileSync(pidfile);
    //REPLACE with your signal or use another method to check process existence :)
root@debvbox:~# cat /etc/dhcp/dhcpd.conf
    process.kill(pid, 'SIGUSR2');
    util.puts('Master already running');
    process.exit(1);
} catch (e) {
    fs.writeFileSync(pidfile, process.pid.toString(), 'ascii');
}


//run your childs here</nowiki>
ddns-update-style none;
 
   
==Библиотеки==
  default-lease-time 259200;
===Socket.IO===
max-lease-time 518400;
 
Socket.IO is a Node.JS project that makes WebSockets and realtime possible in all browsers. It also enhances WebSockets by providing built-in multiplexing, horizontal scalability, automatic JSON encoding/decoding, and more.
authoritative;
 
'''Установка'''
 
npm install socket.io
 
'''Использование'''
 
First, require socket.io:
 
var io = require('socket.io');
 
Next, attach it to a HTTP/HTTPS server. If you're using the fantastic express web framework:
 
Express 3.x
 
  <nowiki>var app = express()
  , server = require('http').createServer(app)
  , io = io.listen(server);
 
server.listen(80);
 
io.sockets.on('connection', function (socket) {
  socket.emit('news', { hello: 'world' });
  socket.on('my other event', function (data) {
    console.log(data);
  });
});</nowiki>
 
 
Finally, load it from the client side code:
 
  <nowiki><script src="/socket.io/socket.io.js"></script>
<script>
  var socket = io.connect('http://localhost');
  socket.on('news', function (data) {
    console.log(data);
    socket.emit('my other event', { my: 'data' });
  });
</script></nowiki>
 
For more thorough examples, look at the examples/ directory.
 
'''Примеры использования'''
 
Sending and receiving events.
 
Socket.IO allows you to emit and receive custom events. Besides connect, message and disconnect, you can emit custom events:
 
// note, io.listen(<port>) will create a http server for you
var io = require('socket.io').listen(80);
 
io.sockets.on('connection', function (socket) {
  io.sockets.emit('this', { will: 'be received by everyone' });
 
  socket.on('private message', function (from, msg) {
    console.log('I received a private message by ', from, ' saying ', msg);
  });
 
  socket.on('disconnect', function () {
    io.sockets.emit('user disconnected');
  });
});
Storing data associated to a client
 
Sometimes it's necessary to store data associated with a client that's necessary for the duration of the session.
 
Server side
 
var io = require('socket.io').listen(80);
 
io.sockets.on('connection', function (socket) {
  socket.on('set nickname', function (name) {
    socket.set('nickname', name, function () { socket.emit('ready'); });
  });
 
  socket.on('msg', function () {
    socket.get('nickname', function (err, name) {
      console.log('Chat message by ', name);
    });
  });
});
Client side
 
<script>
  var socket = io.connect('http://localhost');
 
  socket.on('connect', function () {
    socket.emit('set nickname', prompt('What is your nickname?'));
    socket.on('ready', function () {
      console.log('Connected !');
      socket.emit('msg', prompt('What is your message?'));
    });
  });
</script>
Restricting yourself to a namespace
 
If you have control over all the messages and events emitted for a particular application, using the default / namespace works.
 
If you want to leverage 3rd-party code, or produce code to share with others, socket.io provides a way of namespacing a socket.
 
This has the benefit of multiplexing a single connection. Instead of socket.io using two WebSocket connections, it'll use one.
 
The following example defines a socket that listens on '/chat' and one for '/news':
 
Server side
 
var io = require('socket.io').listen(80);
 
var chat = io
  .of('/chat')
  .on('connection', function (socket) {
    socket.emit('a message', { that: 'only', '/chat': 'will get' });
    chat.emit('a message', { everyone: 'in', '/chat': 'will get' });
  });
 
var news = io
  .of('/news');
  .on('connection', function (socket) {
    socket.emit('item', { news: 'item' });
  });
Client side:
 
<script>
  var chat = io.connect('http://localhost/chat')
    , news = io.connect('http://localhost/news');
 
  chat.on('connect', function () {
    chat.emit('hi!');
  });
 
  news.on('news', function () {
    news.emit('woot');
  });
</script>
Sending volatile messages.
 
Sometimes certain messages can be dropped. Let's say you have an app that shows realtime tweets for the keyword bieber.
 
If a certain client is not ready to receive messages (because of network slowness or other issues, or because he's connected through long polling and is in the middle of a request-response cycle), if he doesn't receive ALL the tweets related to bieber your application won't suffer.
 
In that case, you might want to send those messages as volatile messages.
 
Server side
 
var io = require('socket.io').listen(80);
 
io.sockets.on('connection', function (socket) {
  var tweets = setInterval(function () {
    getBieberTweet(function (tweet) {
      socket.volatile.emit('bieber tweet', tweet);
    });
  }, 100);
 
  socket.on('disconnect', function () {
    clearInterval(tweets);
  });
});
Client side
 
In the client side, messages are received the same way whether they're volatile or not.
 
Getting acknowledgements
 
Sometimes, you might want to get a callback when the client confirmed the message reception.
 
To do this, simply pass a function as the last parameter of .send or .emit. What's more, when you use .emit, the acknowledgement is done by you, which means you can also pass data along:
 
Server side
 
var io = require('socket.io').listen(80);
 
io.sockets.on('connection', function (socket) {
  socket.on('ferret', function (name, fn) {
    fn('woot');
  });
});
Client side
 
<script>
  var socket = io.connect(); // TIP: .connect with no args does auto-discovery
  socket.on('connect', function () { // TIP: you can avoid listening on `connect` and listen on events directly too!
    socket.emit('ferret', 'tobi', function (data) {
      console.log(data); // data will be 'woot'
    });
  });
</script>
Broadcasting messages
 
To broadcast, simply add a broadcast flag to emit and send method calls. Broadcasting means sending a message to everyone else except for the socket that starts it.
 
Server side
 
var io = require('socket.io').listen(80);
 
io.sockets.on('connection', function (socket) {
  socket.broadcast.emit('user connected');
  socket.broadcast.json.send({ a: 'message' });
});
Rooms
 
Sometimes you want to put certain sockets in the same room, so that it's easy to broadcast to all of them together.
 
Think of this as built-in channels for sockets. Sockets join and leave rooms in each socket.
 
Server side
 
var io = require('socket.io').listen(80);
 
io.sockets.on('connection', function (socket) {
  socket.join('justin bieber fans');
  socket.broadcast.to('justin bieber fans').emit('new fan');
  io.sockets.in('rammstein fans').emit('new non-fan');
});
Using it just as a cross-browser WebSocket
 
If you just want the WebSocket semantics, you can do that too. Simply leverage send and listen on the message event:
 
Server side
 
var io = require('socket.io').listen(80);
 
io.sockets.on('connection', function (socket) {
  socket.on('message', function () { });
  socket.on('disconnect', function () { });
});
Client side
 
<script>
  var socket = io.connect('http://localhost/');
  socket.on('connect', function () {
    socket.send('hi');
 
    socket.on('message', function (msg) {
      // my msg
    });
  });
</script>
Changing configuration
 
Configuration in socket.io is TJ-style:
 
Server side
 
var io = require('socket.io').listen(80);
 
io.configure(function () {
  io.set('transports', ['websocket', 'flashsocket', 'xhr-polling']);
});
 
io.configure('development', function () {
  io.set('transports', ['websocket', 'xhr-polling']);
  io.enable('log');
});
====Перевод документации с оф. сайта====
'''Использование Node HTTP server'''
 
Установить npm install socket.io
 
'''''SERVER (APP.JS)'''''
 
<nowiki>var app = require('http').createServer(handler)
  , io = require('socket.io').listen(app)
  , fs = require('fs')
   
   
  app.listen(80);
  log-facility local7;
  #параметры настроек сети которые будет получать клиент..
shared-network debvbox {
    option nis-domain                  "debvbox";
    option domain-name                  "debvbox";
    option domain-name-servers          10.10.5.1;
   
    subnet 10.10.5.0 netmask 255.255.255.0 {
    #range 10.10.5.50 10.10.5.60;
    option routers                      10.10.5.1;
    option subnet-mask                  255.255.255.0;
    option broadcast-address            10.10.5.255;
    option time-offset                  -5;     # Eastern Standard Time
    }
   
   
  function handler (req, res) {
  ########################MAC ADDDRESS ALL################# 
  fs.readFile(__dirname + '/index.html',
# здесь прописываем нашего будущего клиента, его мак адрес и.т.д.
  function (err, data) {
    host vclient {
    if (err) {
    option host-name "vclient";
      res.writeHead(500);
    hardware ethernet 08:00:27:35:BA:D9;
      return res.end('Error loading index.html');
    fixed-address 10.10.5.65;
    }
# этот параметр говорит какой образ загрузчика брать.. об этом дальше..  
    res.writeHead(200);
    filename "pxelinux.0";
    res.end(data);
    }
  });
}
   
   
  io.sockets.on('connection', function (socket) {
* теперь прописываем какой интерфейс будет слушать сервер dhcp
  socket.emit('news', { hello: 'world' });
  root@debvbox:~# cat /etc/default/isc-dhcp-server
  socket.on('my other event', function (data) {
    console.log(data);
  });
});</nowiki>


'''''CLIENT (INDEX.HTML)'''''
# Defaults for dhcp initscript
 
  # sourced by /etc/init.d/dhcp
  <nowiki><script src="/socket.io/socket.io.js"></script>
  # installed at /etc/default/isc-dhcp-server by the maintainer scripts
  <script>
  var socket = io.connect('http://localhost');
#
 
  # This is a POSIX shell fragment
  socket.on('news', function (data) {
#
    console.log(data);
    socket.emit('my other event', { my: 'data' });
# On what interfaces should the DHCP server (dhcpd) serve DHCP requests?
  });
  #      Separate multiple interfaces with spaces, e.g. "eth0 eth1".
  </script></nowiki>
INTERFACES="eth0"
 
'''Использование совместно с Express 3 web framework'''
 
Express 3 requires that you instantiate a `http.Server` to attach socket.io to first:
 
 
'''''SERVER (APP.JS)'''''
 
  var app = require('express')()
  , server = require('http').createServer(app)
  , io = require('socket.io').listen(server);
   
   
  server.listen(80);
* в данном случае как видно это интерфейс - eth0
* теперь перезапускаем сервер dhcp и на этом настройка первого этапа закончена.
  root@debvbox:~# /etc/init.d/isc-dhcp-server restart
   
   
  app.get('/', function (req, res) {
  Stopping ISC DHCP server: dhcpd.
  res.sendfile(__dirname + '/index.html');
  Starting ISC DHCP server: dhcpd.
  });
 
io.sockets.on('connection', function (socket) {
  socket.emit('news', { hello: 'world' });
  socket.on('my other event', function (data) {
    console.log(data);
  });
});


'''''CLIENT (INDEX.HTML)'''''
3. '''Настройка сервера TFTP - HPA'''
* создаем каталог, где будет наша будущая система клиента в окружении chroot
root@debvbox:~#mkdir /ltsp


<nowiki><script src="/socket.io/socket.io.js"></script>
* прописываем для сервера tftp-hpa где будет наша "платформа"
  <script>
  root@debvbox:~#cat /etc/default/tftpd-hpa
  var socket = io.connect('http://localhost');
 
  socket.on('news', function (data) {
    console.log(data);
    socket.emit('my other event', { my: 'data' });
  });
</script></nowiki>


'''Использование совместно с Express web framework'''
  # /etc/default/tftpd-hpa
TFTP_USERNAME="tftp"
TFTP_DIRECTORY="/ltsp/boot/"
TFTP_ADDRESS="0.0.0.0:69"
TFTP_OPTIONS="--secure"
* перезапускаем сервер tftp-hpa
root@debvbox:/etc# /etc/init.d/tftpd-hpa restart


You can serve normal pages and AJAX requests with Express, and attach your socket.io server
Restarting HPA's tftpd: in.tftpd.


For this example, simply run `npm install socket.io express`
Проверяем:
netstat -lnp | grep :69


'''''SERVER (APP.JS)'''''
udp        0      0 0.0.0.0:69              0.0.0.0:*                          16665/in.tftpd


var app = require('express').createServer()
  , io = require('socket.io').listen(app);
app.listen(80);
app.get('/', function (req, res) {
  res.sendfile(__dirname + '/index.html');
});
io.sockets.on('connection', function (socket) {
  socket.emit('news', { hello: 'world' });
  socket.on('my other event', function (data) {
    console.log(data);
  });
});


'''''CLIENT (INDEX.HTML)'''''


<nowiki><script src="/socket.io/socket.io.js"></script>
4. '''Настройка сервера LTSP'''
<script>
*Корневая файловая система, которую будут использовать клиенты, находится в каталоге /ltsp. Она должна быть доступна через NFS. Настраивается все это через конфиг /etc/exports
  var socket = io.connect('http://localhost');
* прописываем настройки для сервера nfs-kernel, nfs-common
  socket.on('news', function (data) {
  root@debvbox:/etc# cat /etc/exports
    console.log(data);
    socket.emit('my other event', { my: 'data' });
  });
  </script></nowiki>


'''Отправка и прием событий.'''
# /etc/exports: the access control list for filesystems which may be exported
#              to NFS clients.  See exports(5).
#
# Example for NFSv2 and NFSv3:
# /srv/homes      hostname1(rw,sync,no_subtree_check) hostname2(ro,sync,no_subtree_check)
#
# Example for NFSv4:
# /srv/nfs4        gss/krb5i(rw,sync,fsid=0,crossmnt,no_subtree_check)
# /srv/nfs4/homes  gss/krb5i(rw,sync,no_subtree_check)
## первый каталог - это система и он в режиме только чтение...
/ltsp/                  *(ro,no_root_squash,async,no_subtree_check)
## второй - это домашняя папка пользователя, и он доступен уже на запись...
/ltsp/home/user/        *(rw,no_root_squash,async,no_subtree_check)


Socket.IO позволяет обрабатывать и отправлять произвольные события. Кроме `connect`, `message` and `disconnect`, можно создавать произвольные события:
Проверяем:
showmount -e
Export list for  nzip:                                                                                                                                       
/home/ltsp/home/user/  *                                                                                                                                     
/home/ltsp/          *


'''''SERVER'''''
* теперь создаем корневую систему для пользователя:
root@debvbox:~# cd /ltsp
root@debvbox:~# ltsp-build-client --arch i386 --dist squeeze --mirror http://ftp.ru.debian.org/debian/ squeeze main
.
.
invoke-rc.d nfs-kernel-server reload
info: LTSP client installation completed successfully


// note, io.listen(<port>) will create a http server for you
* заходим в режиме chroot в каталог /ltsp
  var io = require('socket.io').listen(80);
  root@debvbox:~# chroot /ltsp
  io.sockets.on('connection', function (socket) {
  root@debvbox:~/#
  io.sockets.emit('this', { will: 'be received by everyone'});
  socket.on('private message', function (from, msg) {
    console.log('I received a private message by ', from, ' saying ', msg);
  });
  socket.on('disconnect', function () {
    io.sockets.emit('user disconnected');
  });
});


'''Прикрепление данных, ассоциированных с клиентом'''
* сразу добавляем пользователя который будет работать..
root@debvbox:~/# adduser user
.
.
successfully


Иногда необходимо хранить данные, ассоциированные с клиентом, что необходимо для продолжении (duration) сессии.
* до устанавливаем необходимые пакеты для работы клиентов..
root@debvbox:~/# apt-get install sudo ntfs-3g ntfsprogs


'''''SERVER'''''
* выходим из режима chroot
  <nowiki>var io = require('socket.io').listen(80);
  exit
  io.sockets.on('connection', function (socket) {
  root@debvbox:~#
  socket.on('set nickname', function (name) {
    socket.set('nickname', name, function () {
      socket.emit('ready');
    });
  });
  socket.on('msg', function () {
    socket.get('nickname', function (err, name) {
      console.log('Chat message by ', name);
    });
  });
});
</nowiki>
'''''CLIENT'''''
<nowiki><script src="/socket.io/socket.io.js"></script>
<script>
  var socket = io.connect('http://localhost');
  socket.on('news', function (data) {
    console.log(data);
    socket.emit('my other event', { my: 'data' });
  });
</script></nowiki>


'''Оборачивание себя (своего кода) в namespace.'''
* прописываем права пользователя user в sudo и group в каталоге среды /ltsp/etc
* теперь нам необходимо настроить загрузку нашего тонкого клиента, чтоб он мог по умолчанию через 15 секунд загружать систему с жесткого диска или выбрав нижнее меню, загрузить уже нашу среду и провести восстановление системы у себя с помощью ntfsclon


Если вы контролируете все сообщения и события в коде, используйте namespace works по умолчанию (default namespace works)
root@debvbox:/ltsp# cat /ltsp/boot/pxelinux.cfg/default
Если вы хотите использовать сторонний код или предоставлять код другим, socket.io предоставляет возможность использования именованных сокетов (namespacing a socket.)


Это полезно при мультиплексировании соединений. Вместо использования двух соединений WebSocket, будет использовано одно.
TIMEOUT 60
PROMPT 0
DEFAULT menu.c32
MENU TITLE BOOT_MENU
MENU COLOR unsel 37;40
MENU COLOR sel 30;47
MENU COLOR border 37;40
MENU COLOR title 37;40
MENU COLOR hotkey 36;40
MENU COLOR tabmsg 36;40
MENU TABMSG Brought to you by Blue Light.
MENU AUTOBOOT
#
#
label WINDOWS
localboot 0
#
label SYSTEM_RECOVERY
kernel vmlinuz
APPEND ro initrd=initrd.img quiet root=/dev/nfs ip=dhcp boot=nfs nfsroot=10.10.5.1:/ltsp/ ramdisk=8192


''''SERVER'''''
* для корректной работы загрузчика скопируем необходимую библиотеку..
 
  cp /ltsp/usr/lib/syslinux/menu.c32 /ltsp/boot/menu.c32
<nowiki>var io = require('socket.io').listen(80);
   
 
* перезапускаем сервер tftp-hpa
var chat = io
  root@debvbox:/etc# /etc/init.d/tftpd-hpa restart
  .of('/chat')
  .on('connection', function (socket) {
    socket.emit('a message', {
        that: 'only'
      , '/chat': 'will get'
    });
    chat.emit('a message', {
        everyone: 'in'
      , '/chat': 'will get'
    });
  });
 
var news = io
  .of('/news')
  .on('connection', function (socket) {
    socket.emit('item', { news: 'item' });
  });</nowiki>
'''''CLIENT'''''
 
  <nowiki><script>
  var chat = io.connect('http://localhost/chat')
    , news = io.connect('http://localhost/news');
 
  chat.on('connect', function () {
    chat.emit('hi!');
  });
 
  news.on('news', function () {
    news.emit('woot');
  });
</script></nowiki>
 
'''Отправка летучих (volatile) сообщений.'''
 
Иногда некоторые сообщения могут быть удалены (отброшены). Скажем, у вас есть приложение, которое показывает в реальном времени количество твитов по ключевому слову Бибер.
 
Если определенный клиент не готов к приему сообщений (из-за медлительности сети или других вопросов, или потому, что он связан через длинные голосования и находится в середине запрос-ответ цикла), если он не получит всех твитов, связанных с Бибер, то ваша заявка не будет страдать.
 
В этом случае, вы можете отправить эти сообщения, как летучие сообщений.
 
'''''SERVER'''''
 
<nowiki>var io = require('socket.io').listen(80);
 
io.sockets.on('connection', function (socket) {
  var tweets = setInterval(function () {
    getBieberTweet(function (tweet) {
      socket.volatile.emit('bieber tweet', tweet);
    });
  }, 100);
 
  socket.on('disconnect', function () {
    clearInterval(tweets);
  });
});</nowiki>
 
'''Отправка и получение данных (подтверждения)'''
 
Иногда, вы можете получить обратный вызов, когда клиент подтвердил прием сообщения.
 
Чтобы сделать это, просто передать функцию в качестве последнего параметра `.send` или `.emit`. Более того, когда вы используете `.emit`, подтверждение было сделано вами, значит, вы также можете продолжить передавать данные.
 
'''''SERVER'''''
 
<nowiki>var io = require('socket.io').listen(80);
 
io.sockets.on('connection', function (socket) {
  socket.on('ferret', function (name, fn) {
    fn('woot');
  });
});</nowiki>
 
'''''CLIENT'''''
 
<nowiki><script>
  var socket = io.connect(); // TIP: .connect with no args does auto-discovery
  socket.on('connect', function () { // TIP: you can avoid listening on `connect` and listen on events directly too!
    socket.emit('ferret', 'tobi', function (data) {
      console.log(data); // data will be 'woot'
    });
  });
</script></nowiki>
 
'''Broadcasting messages.'''
 
To broadcast, simply add a `broadcast` flag to `emit` and `send` method calls. Broadcasting means sending a message to everyone else except for the socket that starts it.
 
'''''SERVER'''''
 
<nowiki>var io = require('socket.io').listen(80);
 
io.sockets.on('connection', function (socket) {
  socket.broadcast.emit('user connected');
});</nowiki>
 
'''Using it just as a cross-browser WebSocket.'''
 
If you just want the WebSocket semantics, you can do that too. Simply leverage `send` and listen on the `message` event:
 
'''''SERVER'''''
 
<nowiki>var io = require('socket.io').listen(80);
 
io.sockets.on('connection', function (socket) {
  socket.on('message', function () { });
  socket.on('disconnect', function () { });
});</nowiki>
 
'''''CLIENT'''''
 
<nowiki><script>
  var socket = io.connect('http://localhost/');
  socket.on('connect', function () {
    socket.send('hi');
 
    socket.on('message', function (msg) {
      // my msg
    });
  });
</script></nowiki>
 
====Примеры кода====
 
http://kuroikaze85.wordpress.com/2010/06/15/socket-io-node-js-game-making/
[http://www.ibm.com/developerworks/ru/library/cl-nodejscloud/ Применение Node.js в качестве полной среды разработки для облачных решений]
<hr>
==Официальная документция==
 
 
* [http://nodejs.org/api/modules.html nodejs.org]
 
* [http://nodeguide.ru/doc/  Руководства по Node.js от Felix’а]
 
* [http://nodebeginner.ru/ Руководства по Node.js упрощенное...]
 
* [http://vremenno.net/js/node-js-for-beginners/ примеры начинающим]
 
==АКСИОМЫ NODE.JS==
Callback-driven парадигма
 
Неблокирующая функция принимает callback последним аргументом:
 
<nowiki>function asuncFunction(arg1,arg2,...,argN, callback){
 
}</nowiki>
 
Callback принимает ошибку первым аргументом, остальные результат:
 
  <nowiki>function callback(error, result1,result2,...resultN){
 
}</nowiki>
 
==Кластер==
[[Кластер на основе NodeJS]] -
 
==Примеры архитектуры==
[[Tactoom.com изнутри — социальная блог-платформа на NodeJS/NoSQL]]
 
==Обработка форм и визуализации через NodeJs==
 
[http://nodejs.ru/665]http://nodejs.ru/665
 
[http://habrahabr.ru/post/138629/]http://habrahabr.ru/post/138629/
 
[http://nodeguide.ru/doc/dailyjs-nodepad/node-tutorial-7/]http://nodeguide.ru/doc/dailyjs-nodepad/node-tutorial-7/
 
[http://habrahabr.ru/post/147571/]http://habrahabr.ru/post/147571/
 
[http://www.pvsm.ru/node-js/12212]http://www.pvsm.ru/node-js/12212
 
[http://www.pixelcom.crimea.ua/rukovodstvo-po-html5-canvas.html]http://www.pixelcom.crimea.ua/rukovodstvo-po-html5-canvas.html
 
:[[Установка node.js в Debian]]


*Express: веб-фреймворк для Node.js. Руководство пользователя
Restarting HPA's tftpd: in.tftpd.
[http://jsman.ru/express/]http://jsman.ru/express/
* пробуем загрузится "тонким" клиентом


* Руководство для начинающих
* [https://habrahabr.ru/post/277783/ полезное...]
[http://vremenno.net/js/node-js-for-beginners/]http://vremenno.net/js/node-js-for-beginners/
 
*Скелет приложения на Node.js с использованием express, mongoose, backbone.js, socket.io
[http://kulakowka.com/tag/express/]http://kulakowka.com/tag/express/
 
*Русскоязычное сообщество Node.js
[http://forum.nodejs.ru/index.php?topic=130.0]http://forum.nodejs.ru/index.php?topic=130.0
 
*[http://www.pvsm.ru/node-js/16286 Установка node.js на VPS]
 
==Технологии спутники==
Перечень модулей  для Node.js https://github.com/joyent/node/wiki/modules
===Node-sync===
[[Node-sync_—_псевдо-синхронное_программирование_на_nodejs_с_использованием_fibers]]
===socket.io===
* [http://socket.io/ socket.io] [[socket.io документация]]
* [http://blog.denivip.ru/index.php/2012/11/разработка-высокопроизводительных-с/ webSocketServer ru]
 
===Express===
*[http://jsman.ru/express/#quickstart Express: веб-фреймворк для Node.js. Руководство пользователя][[Express: веб-фреймворк для Node.js. Руководство пользователя|Сохраненная копия]]
 
==Отладка и сборка==
*[http://nodejs.ru/324 Отладчик ndb]
*[http://jsman.ru/2012/08/24/browserify.html Browserify - cобираем JS-проект]
*[[JavaScript Strict Mode]]
 
==Примеры кода==
===Цепочка вызывающих себя через callback'и функций с передачей данных следующей функции (обработка ошибок в одном месте, массив функций в качестве параметра)===
 
С использованием async это пишется так:
 
<nowiki>var async = require('async');
 
async.waterfall([
    function(callback){
        setTimeout(function() {
            console.log('f1 done');
            callback(null, 'data from f1');
        }, 100);
    },
    function(data, callback){
        // работа с data
        // или расширение цепочки через функцию f3, которая по окончании работы вызовет callback
        // f3(callback);
        console.log('f2 done');
        callback(null, 'done');
    }
], function (err, result) {
    // result now equals 'done'
    if (err) {
        // единое место для отлова ошибок
    }
    console.log(result);
});</nowiki>
 
== Дополнительные возможности nodejs ==
 
* [http://docs.nodejitsu.com/articles/child-processes/how-to-spawn-a-child-process вызов сторонних команд]
 
== Полезные ресурсы ==
* [http://nodejs.org/download/ node.js]
* [http://nodejs.ru/707 коротко о всех командах node.js]
 
* [http://www.askdev.ru/blog/nodejs/54/Отличное-руководство-для-начинающих-по-Node-js/ полезное на старте.]
* [http://vremenno.net/js/node-js-for-beginners/ примеры кода]
* [http://habrahabr.ru/post/102717/ примеры с Хабра]
* [http://drumcoder.co.uk/blog/2011/jan/10/nodejs-phone-book/ пример работы с postgresql]
 
* [http://jade-lang.com/ .. не все понял но здорово.."шаблнизатор"]
* [https://github.com/visionmedia/jade#readme описание шаблонизатора..]
* [http://www.mongodb.org/ база данных под node.js]
* [http://www.pvsm.ru/web-razrabotka/2198/print/ то что нужно знать!]
* [http://www.slideshare.net/yurabogdanov/nodejs-8223169 профи советы]
* [http://habrahabr.ru/post/130345/ чужой опыт...]
* [http://habrahabr.ru/post/138071/ еще чужой опыт...]
<hr>
''''''Отладка в Node.Js''''''
* [https://github.com/ajaxorg/cloud9 среда разработки для node.js]
* [https://github.com/dannycoates/node-inspector отлачик для node.js]
* [http://habrahabr.ru/post/114825/ использование node-inspector]
* [http://nodejs.ru/doc/v0.4.x/debugger.html встроенный отладчик]
* [http://nodejs.ru/324 Ndb отладка в node]
<hr>
* [[Node.js debian init.script]]
<hr>
<hr>
'''''@модули для node.js'''''
* [https://habr.com/ru/company/serverclub/blog/250549/ Загрузочный сервер — как загрузочная флешка, только сервер и по сети]
* [http://thechangelog.com/stylus-expressive-robust-feature-rich-css-language/ stylus - работа со стилями через nod.js]

Текущая версия от 22:16, 28 августа 2020

ПОЭТАПНОЕ РУКОВОДСТВО ПО УСТАНОВКЕ И НАСТРОЙКЕ ТОНКОГО КЛИЕНТА НА ПЛАТФОРМЕ Linux Debian Squeeze

  • И так, собрав в кучу все имеющееся руководство по настройке "тонкого" клиента и перебрав всевозможные

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

  • Применительно к ситуации, создадим "тонкого" клиента, с возможностью обслуживания разделов жесткого диска,

в частности с возможностью сохранения или восстановления образов партиций NTFS по сети.

  • Далее по порядку:

1. Устанавливаем необходимые пакеты:

apt-get install isc-dhcp-server tftpd-hpa ltsp-server nfs-common nfs-kernel-server
  • рекомендуется после установки запустить программу aptitude и до установить требуемые пакеты, если есть такой запрос...
  • при установке сервера tftpd-hpa он будет просить вас указать каталог где будет "платформа", согласитесь по умолчанию /srv/tftp или /opt/ltsp, все равно потом это будем менять..

2. Теперь настраиваем сервер DHCP:

  • предположим что наша сеть такая:
root@debvbox:~#cat /etc/network/interfaces
# The loopback network interface
auto lo
iface lo inet loopback

# The primary network interface
auto eth0
iface eth0 inet static
        address 10.10.5.1
        netmask 255.255.255.0
        network 10.10.5.0
        broadcast 10.10.5.255
        gateway 10.10.5.1
        dns-nameservers 10.10.5.1
  • Исходя из этих данных настраиваем наш dhcp сервер:
root@debvbox:~# cat /etc/dhcp/dhcpd.conf 
ddns-update-style none;

default-lease-time 259200;
max-lease-time 518400;

authoritative;

log-facility local7;
 #параметры настроек сети которые будет получать клиент..
shared-network debvbox {
    option nis-domain                   "debvbox";
    option domain-name                  "debvbox";
    option domain-name-servers          10.10.5.1;
   
    subnet 10.10.5.0 netmask 255.255.255.0 {
    #range 10.10.5.50 10.10.5.60;
    option routers                      10.10.5.1;
    option subnet-mask                  255.255.255.0;
    option broadcast-address            10.10.5.255;
    option time-offset                  -5;     # Eastern Standard Time
    }

########################MAC ADDDRESS ALL#################  
# здесь прописываем нашего будущего клиента, его мак адрес и.т.д.
    host vclient {
    option host-name "vclient";
    hardware ethernet 08:00:27:35:BA:D9;
    fixed-address 10.10.5.65;
# этот параметр говорит какой образ загрузчика брать.. об этом дальше.. 
    filename "pxelinux.0";
    }

  • теперь прописываем какой интерфейс будет слушать сервер dhcp
root@debvbox:~# cat /etc/default/isc-dhcp-server
# Defaults for dhcp initscript
# sourced by /etc/init.d/dhcp
# installed at /etc/default/isc-dhcp-server by the maintainer scripts 

#
# This is a POSIX shell fragment
# 

# On what interfaces should the DHCP server (dhcpd) serve DHCP requests?
#       Separate multiple interfaces with spaces, e.g. "eth0 eth1".
INTERFACES="eth0"

  • в данном случае как видно это интерфейс - eth0
  • теперь перезапускаем сервер dhcp и на этом настройка первого этапа закончена.
root@debvbox:~# /etc/init.d/isc-dhcp-server restart

Stopping ISC DHCP server: dhcpd.
Starting ISC DHCP server: dhcpd.

3. Настройка сервера TFTP - HPA

  • создаем каталог, где будет наша будущая система клиента в окружении chroot
root@debvbox:~#mkdir /ltsp
  • прописываем для сервера tftp-hpa где будет наша "платформа"
root@debvbox:~#cat /etc/default/tftpd-hpa
# /etc/default/tftpd-hpa

TFTP_USERNAME="tftp"
TFTP_DIRECTORY="/ltsp/boot/"
TFTP_ADDRESS="0.0.0.0:69"
TFTP_OPTIONS="--secure"
  • перезапускаем сервер tftp-hpa
root@debvbox:/etc# /etc/init.d/tftpd-hpa restart
Restarting HPA's tftpd: in.tftpd.

Проверяем:

netstat -lnp | grep :69
udp        0      0 0.0.0.0:69              0.0.0.0:*                           16665/in.tftpd


4. Настройка сервера LTSP

  • Корневая файловая система, которую будут использовать клиенты, находится в каталоге /ltsp. Она должна быть доступна через NFS. Настраивается все это через конфиг /etc/exports
  • прописываем настройки для сервера nfs-kernel, nfs-common
root@debvbox:/etc# cat /etc/exports
# /etc/exports: the access control list for filesystems which may be exported
#               to NFS clients.  See exports(5).
#
# Example for NFSv2 and NFSv3:
# /srv/homes       hostname1(rw,sync,no_subtree_check) hostname2(ro,sync,no_subtree_check)
#
# Example for NFSv4:
# /srv/nfs4        gss/krb5i(rw,sync,fsid=0,crossmnt,no_subtree_check)
# /srv/nfs4/homes  gss/krb5i(rw,sync,no_subtree_check)
## первый каталог - это система и он в режиме только чтение... 
/ltsp/                  *(ro,no_root_squash,async,no_subtree_check)
## второй - это домашняя папка пользователя, и он доступен уже на запись...
/ltsp/home/user/        *(rw,no_root_squash,async,no_subtree_check)

Проверяем:

showmount -e

Export list for  nzip:                                                                                                                                        
/home/ltsp/home/user/  *                                                                                                                                      
/home/ltsp/           * 
  • теперь создаем корневую систему для пользователя:
root@debvbox:~# cd /ltsp
root@debvbox:~# ltsp-build-client --arch i386 --dist squeeze --mirror http://ftp.ru.debian.org/debian/ squeeze main
.
.
invoke-rc.d nfs-kernel-server reload
info: LTSP client installation completed successfully
  • заходим в режиме chroot в каталог /ltsp
root@debvbox:~# chroot /ltsp
root@debvbox:~/#
  • сразу добавляем пользователя который будет работать..
root@debvbox:~/# adduser user
.
.
successfully
  • до устанавливаем необходимые пакеты для работы клиентов..
root@debvbox:~/# apt-get install sudo ntfs-3g ntfsprogs
  • выходим из режима chroot
exit
root@debvbox:~#
  • прописываем права пользователя user в sudo и group в каталоге среды /ltsp/etc
  • теперь нам необходимо настроить загрузку нашего тонкого клиента, чтоб он мог по умолчанию через 15 секунд загружать систему с жесткого диска или выбрав нижнее меню, загрузить уже нашу среду и провести восстановление системы у себя с помощью ntfsclon
root@debvbox:/ltsp# cat /ltsp/boot/pxelinux.cfg/default
TIMEOUT 60
PROMPT 0
DEFAULT menu.c32
MENU TITLE BOOT_MENU
MENU COLOR unsel 37;40
MENU COLOR sel 30;47
MENU COLOR border 37;40
MENU COLOR title 37;40
MENU COLOR hotkey 36;40
MENU COLOR tabmsg 36;40
MENU TABMSG Brought to you by Blue Light.
MENU AUTOBOOT
#
#
label WINDOWS 
localboot 0
#
label SYSTEM_RECOVERY
kernel vmlinuz
APPEND ro initrd=initrd.img quiet root=/dev/nfs ip=dhcp boot=nfs nfsroot=10.10.5.1:/ltsp/ ramdisk=8192
  • для корректной работы загрузчика скопируем необходимую библиотеку..
cp /ltsp/usr/lib/syslinux/menu.c32 /ltsp/boot/menu.c32

  • перезапускаем сервер tftp-hpa
root@debvbox:/etc# /etc/init.d/tftpd-hpa restart
Restarting HPA's tftpd: in.tftpd.
  • пробуем загрузится "тонким" клиентом