forked from cloudlinux/cloudlinux-doc
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtmp
More file actions
763 lines (757 loc) · 85.6 KB
/
tmp
File metadata and controls
763 lines (757 loc) · 85.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
<td>4000</td>
<td>Y</td>
<td>5</td>
<td>analyzes usage of LVE</td>
</tr>
<tr>
<td>LveUsageAggregator</td>
<td>5000</td>
<td>Y</td>
<td>60</td>
<td>aggregates data by time periods</td>
</tr>
<tr>
<td>DBGovSaver</td>
<td>6000</td>
<td>Y</td>
<td>5</td>
<td>Saves data about database governor</td>
</tr>
<tr>
<td>FileSaver</td>
<td>7000</td>
<td>Y</td>
<td>5</td>
<td>Saves LVE data into /var/lve/info</td>
</tr>
<tr>
<td>CloudLinuxTopFileSaver</td>
<td>8000</td>
<td>Y</td>
<td>60</td>
<td>saves data used by <span class="notranslate"> cloudlinux-top </span> to /var/lve/cloudlinux-top.json</td>
</tr>
<tr>
<td>DBSaver</td>
<td>9000</td>
<td>Y</td>
<td>60</td>
<td>save LVE data to dabase</td>
</tr>
<tr>
<td>DbUsernamesSaver</td>
<td>10000</td>
<td>Y</td>
<td>3600</td>
<td>saves users name to database</td>
</tr>
<tr>
<td>DBSaverX60</td>
<td>11000</td>
<td>Y</td>
<td>3600</td>
<td>saves aggregated hourly data into database</td>
</tr>
<tr>
<td>SnapshotSaver</td>
<td>12000</td>
<td>Y</td>
<td>30</td>
<td>collects & saves snapshots data</td>
</tr>
<tr>
<td>StatsNotifier</td>
<td>13000</td>
<td>Y</td>
<td>varied</td>
<td>notify user/admin based on usage</td>
</tr>
<tr>
<td>HistoryCleaner</td>
<td>14000</td>
<td>Y</td>
<td>3600</td>
<td>removes old usage</td>
</tr>
<tr>
<td>ResMEMCollector</td>
<td>1500</td>
<td>N</td>
<td>30</td>
<td>collects physical memory usage from processes RES field instead of /proc/lve/list</td>
</tr>
<tr>
<td>LVEDestroyer</td>
<td>-</td>
<td>N</td>
<td>5</td>
<td>destroys LVEs that weren't active for X iterations. Number of iterations is passed from config using iterations variable. <span class="notranslate"> iterations=0 </span> means plugin disabled</td>
</tr>
</tbody>
</table>
<p>To enable non-default plugin, copy or link it to _ /usr/share/lve-stats/plugins_ directory.</p>
<p>For example to enable _ ResMEMCollector_ plugin, do:</p>
<p><span class="notranslate"> </span></p>
<!--beforebegin--><div class="language- extra-class"><!--afterbegin--><pre v-pre class="language-text"><code>ln -s /usr/share/lve-stats/plugins.other/res_mem_collector.py /usr/share/lve-stats/plugins/service lvestats restart
</code></pre>
<!--beforeend--></div><!--afterend--><h2 id="creating-a-plugin-for"><a class="header-anchor" href="#creating-a-plugin-for" aria-hidden="true">#</a> Creating a Plugin for</h2>
<p><router-link to="/lve-stats_2/#introduction">Introduction</router-link></p>
<p><router-link to="/lve-stats_2/#server-plugin-arrangement">Server Plugin Arrangement</router-link></p>
<p><router-link to="/lve-stats_2/#plugin-configuration">Plugin Configuration</router-link></p>
<p><router-link to="/lve-stats_2/#types-of-plugins">Types of Plugins</router-link></p>
<h3 id="introduction"><a class="header-anchor" href="#introduction" aria-hidden="true">#</a> Introduction</h3>
<p><span class="notranslate"> LVE Stats 2 </span> complex has scalable architecture, which allows to connect custom plugins.</p>
<p><span class="notranslate"> LVE Stats </span> server searches for plugins in the directory which is specified with plugins parameter of server’s /etc/sysconfig/lvestats2 configuration file. Default directory is _ _ /usr/share/lve-stats/plugins.</p>
<p>Each plugin must be of a <span class="notranslate"> Python </span> class, must be written in <span class="notranslate"> Python </span> language and its file must have <span class="notranslate"> .py </span> extension. Files with all other extensions will be ignored. For normal server work access permission 400 is enough; owner – <span class="notranslate"> root </span> .</p>
<p>Plugins' classes can be of the same name, but better not, because classes' names can affect the set of parameters in <em>set_config</em> method. You can find detailed plugins' configuring information below, in appropriate chapter.</p>
<p>Plugin's class must contain <span class="notranslate"> <em>execute()</em> </span> method, which is invoked by the server every 5 seconds (by default, can be changed by interval parameter of configuration file).
Also <span class="notranslate"> set_config </span> method (configuration settings) can be available. You can find more info in <span class="notranslate"> Plugins Configuration </span> chapter.</p>
<p>Additionally the following attributes can be set (plugin class instance variable):</p>
<p><span class="notranslate"> order (integer) </span> - defines plugin's position in the server's plugin list, (more info in <span class="notranslate"> Servers Plugin Arrangement </span> ).
<span class="notranslate"> timeout (integer </span> or <span class="notranslate"> float </span> ) – the longest allowable duration of one launch of the plugin (execute method). Default value of <span class="notranslate"> timeout </span> parameter is 5 seconds.
<span class="notranslate"> period (integer) </span> – sets the interval between two launches of execute plugin method in seconds. If not defined, then plugin runs every 5 seconds ( <span class="notranslate"> interval </span> parameter in configuration file).</p>
<p>When <span class="notranslate"> <em>execute()</em> </span> method of the plugin is invoked, the server creates an attribute <span class="notranslate"> <em>now</em> </span> in it, where launch time is recorded. This value is equal to what a standard Python function <em>time.time()</em> returns. All the plugins launched one after another receive the same value of <span class="notranslate"> <em>now</em> </span> attribute from the server. <span class="notranslate"> <em>now</em> </span> is overwritten before <span class="notranslate"> <em>execute()</em> </span> method is invoked.</p>
<p>The previous value of now attribute is not saved by the server. If plugin needs it, it has to save it by itself.</p>
<p>Plugin's class can be inherited from <span class="notranslate"> <em>LveStatsPlugin</em> </span> class, which is the part of the server itself. This is not obligatory, but inheritance can help to avoid different errors in servers work, particularly if a plugin doesn't contain required execute method.</p>
<p><span class="notranslate"> <em>LveStatsPlugin</em> </span> class is defined in the file: <em>/opt/alt/python27/lib/python2.7/site-packages/lvestats/core/plugin.py</em> .</p>
<h3 id="server-plugin-arrangement"><a class="header-anchor" href="#server-plugin-arrangement" aria-hidden="true">#</a> Server Plugin Arrangement</h3>
<p>When the server starts, it performs the search of plugins in the directory specified in /etc/sysconfig/lvestats2 configuration file. This directory is scanned only when the server starts, therefore if any plugin was added into the directory, the server has to be restarted with the following command:
<span class="notranslate"> </span></p>
<!--beforebegin--><div class="language- extra-class"><!--afterbegin--><pre v-pre class="language-text"><code>service lvestats restart.
</code></pre>
<!--beforeend--></div><!--afterend--><p>After successful restart the plugins are graded and executed ascending by <span class="notranslate"> <em>order</em> </span> attribute. If any plugin's <span class="notranslate"> <em>order</em> </span> attribute is not set, it is considered as a Python language constant <em>sys.maxint</em> (which is usually 9223372036854775807). This in fact means that such plugins will be executed in the last.
If any plugins has similar <span class="notranslate"> <em>order</em> </span> meanings, their execution order is unpredictable.</p>
<p>The server invokes <span class="notranslate"> <em>execute</em> </span> method of all plugins one after another.</p>
<p>When the server invokes <span class="notranslate"> <em>execute()</em> </span> method of any plugin, it transmits a data dictionary ( <em>lve_data</em> argument) into plugin. The dictionary is common for all the plugins. Any plugin can read, write and change any data in this dictionary. <span class="notranslate"> LVE Stats 2 </span> server doesn't control this area. That is why one must be careful while developing new plugins, in order not to change or corrupt other plugins' data which can break their functionality.</p>
<p>If an exception occurs in <span class="notranslate"> <em>execute()</em> </span> method, its text and python stack trace is recorded into server log /var/log/lve-stats and all the changes made to <em>lve_data</em> dictionary before the exception happened are lost.</p>
<p>The keys of the <em>lve_data</em> dictionary are recommended to look like <span class="notranslate"> “ <em>PluginName_Key</em> ” </span> , in order the plugins do not corrupt other data accidentally.</p>
<p>Server contains some standard plugins which define and use the following keys in the common dictionary lve_data: <span class="notranslate"> <em>LVE_VERSION, stats, old_stats, procs</em> </span> and <span class="notranslate"> <em>lve_usage</em> </span> . User plugins can use data from these keys, but it is recommended not to change them if there is no special need, because it can break the next plugins in the execution queue.</p>
<table>
<thead>
<tr>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
<tr>
<td>Key</td>
<td>Content</td>
</tr>
<tr>
<td><span class="notranslate"> <code>LVE_VERSION</code> </span></td>
<td>LVE version. The same as console command <code>lvectl lve-version produces.</code></td>
</tr>
<tr>
<td><span class="notranslate"> <code>stats</code> </span></td>
<td>Dictionary, that contains lve id’s as keys and LVEStat class objects as values. Every LVEStat object contains values of usages and limits taken from /proc/lve/list file for every <span class="notranslate"> LVE Id </span> . Dictionary keys – <span class="notranslate"> integer lve id </span> , including 0 for “ <span class="notranslate"> default </span> ” LVE. This dictionary is updated on each iteration of lvestats-server (every 5 seconds by default). LVEStat – is a standard server class, it can be imported with the command from <em>lvestats.core.lvestat</em> <code>import LVEStat.</code> The class is described in the file /opt/alt/python27/lib/python2.7/site-packages/lvestats/core/lvestat.py. Here you can find the whole list of data fields and their functions.</td>
</tr>
<tr>
<td><span class="notranslate"> <code>old_stats</code> </span></td>
<td><em>stats</em> content from the previous iteration. Before the first iteration – empty dictionary.</td>
</tr>
<tr>
<td><span class="notranslate"> <code>totalHz</code> </span></td>
<td>When LVE_VERSION is 4, real <span class="notranslate"> CPU </span> frequency in <span class="notranslate"> Hz </span> multiplied by number of cores. When LVE_VERSION > 4, <span class="notranslate"> CPU </span> speed is in conventional units and equals to 1000000000 * cores (1 <span class="notranslate"> GHz </span> per core).</td>
</tr>
<tr>
<td><span class="notranslate"> <code>procs</code> </span></td>
<td>Quantity of <span class="notranslate"> CPU </span> /cores.</td>
</tr>
<tr>
<td><span class="notranslate"> <code>lve_usages</code> </span></td>
<td>Contains accumulated LVE statistics for each 5-seconds interval in current minute. Cleared each minute.</td>
</tr>
<tr>
<td><span class="notranslate"> <code>lve_usage</code> </span></td>
<td>Contains aggregated LVE Statistics for “previous” minute to store to database. Overwritten each minute.</td>
</tr>
</tbody>
</table>
<p>Each plugin’s instance lifetime is from the moment it was loaded till the server stops working. But if <span class="notranslate"> <em>execute()</em> </span> method working time exceeds timeout, the plugin will be terminated and restarted in the next iteration. All changes to the <em>lve_data</em> dictionary will be lost.</p>
<p>During servers graceful shutdown (restart, server shutdown, commands <span class="notranslate"> <code>service lvestats stop, service lvestats restart</code> </span> ), each plugin receives SIGTERM signal.
This is useful to correctly unload the plugin (terminate all subsidiary processes, save data to files etc.). If a plugin doesn't need to “finalize” its execution before termination, then there's no need to implement this signal handler. Below you can see an example of such handler.</p>
<h3 id="plugin-configuration"><a class="header-anchor" href="#plugin-configuration" aria-hidden="true">#</a> Plugin Configuration</h3>
<p><span class="notranslate"> LVE Stats 2 </span> Server allows to configure each plugin separately.</p>
<p>On initialization stage the server invokes <span class="notranslate"> <em>set_config()</em> </span> method of the plugin and locates there a dictionary which contains:</p>
<p>all parameters from file /etc/sysconfig/lvestats2 (global).
plugin's individual configuration file parameters (if one exists). Configuration files must be located in /etc/sysconfig/lvestats.config directory, have .cfg extension and be the same format as /etc/sysconfig/lvestats2. Files in this directory are matched with the plugins by name. For instance, if plugin's class is <span class="notranslate"> <em>Plugin1_class</em> </span> , then server will try to find and download /etc/sysconfig/lvestats.config/Plugin1_class.cfg. Names are case sensitive. If any plugin doesn't have an individual configuration file, then it's not an error. In this case plugin will just receive parameters from /etc/sysconfig/lvestats2.</p>
<h3 id="types-of-plugins"><a class="header-anchor" href="#types-of-plugins" aria-hidden="true">#</a> Types of Plugins</h3>
<p>According to server architecture, plugins can be of the following types:</p>
<p><span class="notranslate"> collectors </span>
<span class="notranslate"> analyzers </span>
<span class="notranslate"> persistors </span>
<span class="notranslate"> notifiers </span></p>
<p><span class="notranslate"> Collectors </span> are designed to collect information; <span class="notranslate"> analyzers </span> – to analyze it and form some other data on its basis; <span class="notranslate"> persistors </span> – to save information from the common dictionary into files, databases, etc.; <span class="notranslate"> notifiers </span> - to notify system users about any events.</p>
<p>This division is rather arbitrary. There is an opportunity to execute all the actions on collection, analysis and saving the information in one and only plugin. But at the same time the division into functionally independent parts allows to build flexible and easily configurable system for collecting and processing the data.</p>
<p>Also it is possible to implement the systems of lazy-write, planning of collecting/processing tasks and notifying users about different events.</p>
<h3 id="examples-of-plugins"><a class="header-anchor" href="#examples-of-plugins" aria-hidden="true">#</a> Examples of Plugins</h3>
<p>Here is a practical example of a user plugin.</p>
<p>Specification:</p>
<ol>
<li>
<p>To trace specified file size changes. The name of file being traced must be specified in configuration file, which allows to change it without modifying the plugin itself. If file size has been changed, it has to be written as a message into our log. The name of log must be specified in configuration file as well.</p>
</li>
<li>
<p>File size must be checked with default interval (5 seconds), and log notification must be held once a minute (to avoid resource expend for possibly regular write).</p>
</li>
<li>
<p>System administrator must receive emails with file size at the moment the email was sent. These notifications must be sent even if the file size hasn’t been changed. Notification emails must be read periodicity from configuration file as well as sender/receiver emails .</p>
</li>
</ol>
<p>As file size check, fixing the result and notification sending must be held with different periods, then it’s impossible to realize all the tasks by means of one plugin.
The fact that one minute (60 seconds) is multiple to 5 seconds doesn’t matter in this case, because default period can be changed in server’s configuration file, but the condition of fixing the result once a minute is a part of the specification, which can not be violated. In addition, notification email period is known in advance, as it is specified by user in configuration file.</p>
<p>That is why we realize 4 plugins: ** ** <span class="notranslate"> collector, analyzer, persistor </span> and <span class="notranslate"> <strong>notifier</strong> </span> .</p>
<h4 id="collector"><a class="header-anchor" href="#collector" aria-hidden="true">#</a> Collector</h4>
<p><span class="notranslate"> <strong>Collector's</strong> </span> aim is to determine the size of a proper file.
<span class="notranslate"> </span></p>
<!--beforebegin--><div class="language- extra-class"><!--afterbegin--><pre v-pre class="language-text"><code># FSize_watcher_collector.py# Example plugin for monitoring file size.# Part 1. Collectorimport osfrom lvestats.core.plugin import LveStatsPlugin # Key nameCOLLECTOR_KEY = 'FSizeWatcher_fsize'COLLECTOR_KEY_FILENAME = 'FSizeWatcher_fname' class FSize_watcher_collector (LveStatsPlugin):# this plugin should be first in chainorder = 0# File to monitoringfile_to_monitoring = None def __init__(self):pass # Sets configuration to plugindef set_config(self, config):self.file_to_monitoring = config.get('file_to_monitoring', None)pass# Work methoddef execute(self, lve_data):try:# if monitoring file absent, do nothingif self.file_to_monitoring is None or not os.path.exists(self.file_to_monitoring):return # Get file sizestat_info = os.stat(self.file_to_monitoring)fsize = stat_info.st_size # Place file name and file size to server data dictionarylve_data[COLLECTOR_KEY_FILENAME] = self.file_to_monitoringlve_data[COLLECTOR_KEY] = fsizeexcept (OSError, IOError):# file absent or any other error - remove size from dictionarydel lve_data[COLLECTOR_KEY]
</code></pre>
<!--beforeend--></div><!--afterend--><p>Plugin algorithm is extremely simple – file size is read and written into data dictionary. Files name is read from <em>set_config</em> method configuration. If the name is not specified, then <span class="notranslate"> None </span> is written into appropriate variable. All the errors are completely ignored (e.g. if specified file doesn't exist or there's no way to read any of it's information).</p>
<p><span class="notranslate"> <em>order</em> </span> attribute is specified as 0 to make this plugin go the first among three. Data collector must always be the first in plugins logical chain, because it provides all the necessary information for the analyzer which goes the next. Specific values of я <span class="notranslate"> <em>order</em> </span> can be of any kind, but what is important is that when the server starts, all the plugins line up in proper sequence: <span class="notranslate"> collector – analyzer – persistor </span> .</p>
<p>In order to make plugin work, we have to create configuration file /etc/sysconfig/lvestats.config/FSize_watcher_collector.cfg with the following content:
<span class="notranslate"> </span></p>
<!--beforebegin--><div class="language- extra-class"><!--afterbegin--><pre v-pre class="language-text"><code># Config file for FSize_watcher_collector plugin# Please define monitoring file here#file_to_monitoring = /usr/local/cpanel/logs/error_logfile_to_monitoring = /usr/local/cpanel/logs/access_log
</code></pre>
<!--beforeend--></div><!--afterend--><p>Note that file’s name <span class="notranslate"> <em>FSize_watcher_collector</em> </span> without .cfg extension matches plugin class name.</p>
<p><span class="notranslate"> <em>file_to_monitoring</em> </span> option is read by plugin in <span class="notranslate"> <em>set_config</em> </span> method and contains file’s full name for monitoring.</p>
<p>Files for monitoring, suggested in the actual example - /usr/local/cpanel/logs/error_log and /usr/local/cpanel/logs/access_log - are real, these are cPanel control panel logs.</p>
<p>The first file is errors log; the second is appeal log, is refreshed during common work with panel (e.g. if user email address is changed).</p>
<p>Errors log tracking is more important, but appeal log monitoring allows to illustrate plugins work more in details, because it is refreshed more often.</p>
<p>Note that plugin can monitor one file only.</p>
<h4 id="analizer"><a class="header-anchor" href="#analizer" aria-hidden="true">#</a> Analizer</h4>
<p><span class="notranslate"> <strong>Analyzer</strong> </span> decides if the file's size has changed and gives a command to persistor to refresh log.</p>
<p><span class="notranslate"> </span></p>
<!--beforebegin--><div class="language- extra-class"><!--afterbegin--><pre v-pre class="language-text"><code># FSize_watcher_analyzer.py# Example plugin for monitoring file size.# Part 2. Analyzer from lvestats.core.plugin import LveStatsPlugin # Key name from collector pluginCOLLECTOR_KEY = 'FSizeWatcher_fsize' # Key name 1 for saver pluginSAVER_KEY = 'FSizeWatcher_fsize_to_store'# Key name 2 for saver pluginSAVER_DATA_PRESENCE = 'FSizeWatcher_fsize_present' class FSize_watcher_analyzer (LveStatsPlugin):# this plugin should be second in chainorder = 1# Last file sizefile_last_size = 0# Plugin run period in secondsperiod = 60 def __init__(self):pass # work methoddef execute(self, lve_data):# Default setting for saverlve_data[SAVER_DATA_PRESENCE] = 0# Check presence dataif COLLECTOR_KEY not in lve_data:return # Get file size from server data dictionaryfsize = lve_data[COLLECTOR_KEY] # Check, if file size changed, store it for saver pluginif fsize == self.file_last_size:return # Put new size for saver pluginlve_data[SAVER_KEY] = fsizeself.file_last_size = fsizelve_data[SAVER_DATA_PRESENCE] = 1
</code></pre>
<!--beforeend--></div><!--afterend--><p>This plugin is extremely simple as well. It starts after <span class="notranslate"> collector (order=1) </span> , searches for file size in the dictionary and compares it with the previous index. If it has changed, then it writes a sign of presence of a new size into the dictionary. If no changes seen, then sign resets. The previous file size is stored in the plugin itself in <span class="notranslate"> <em>file_last_size</em> </span> variable. Note that they are stored during the whole server <span class="notranslate"> lve-stats </span> lifetime.</p>
<p>If file size is not found in data dictionary, then plugin just ends.</p>
<p>All the errors are completely ignored.</p>
<p><span class="notranslate"> Analyzer </span> is unconfigurable, that is why it doesn’t require any configuration file and it doesn’t contain <span class="notranslate"> <em>set_config</em> </span> method.</p>
<p>Plugin starts every 60 seconds (1 minute), because we need data fixation to be performed one time in a minute.</p>
<h4 id="persistor"><a class="header-anchor" href="#persistor" aria-hidden="true">#</a> Persistor</h4>
<p><span class="notranslate"> <strong>Persistor</strong> </span> saves information from the common dictionary into files, databases, etc.
<span class="notranslate"> </span></p>
<!--beforebegin--><div class="language- extra-class"><!--afterbegin--><pre v-pre class="language-text"><code># FSize_watcher_saver.py# Example plugin for monitoring file size and last modification date-time.# Part 3. Data saver import signalimport sysimport timefrom lvestats.core.plugin import LveStatsPlugin # Key name 1 for saver pluginSAVER_KEY = 'FSizeWatcher_fsize_to_store'# Key name 2 for saver pluginSAVER_DATA_PRESENCE = 'FSizeWatcher_fsize_present'# Monitoring file nameCOLLECTOR_KEY_FILENAME = 'FSizeWatcher_fname' class FSize_watcher_saver (LveStatsPlugin):# this plugin should be third in chainorder = 2# Plugin run period in secondsperiod = 60# Log filenamelog_file_name = None# First run flagis_first_run = True def __init__(self):signal.signal(signal.SIGTERM, self.sigterm_handler) # Sets configuration to plugindef set_config(self, config):# Get log filenameself.log_file_name = config.get('log_filename', None) # work methoddef execute(self, lve_data):# do nothing, if log file not definedif not self.log_file_name:returntry:# Check presence dataif SAVER_DATA_PRESENCE not in lve_data or lve_data[SAVER_DATA_PRESENCE] == 0:# No datareturn# Get file size from server data dictionaryfsize = lve_data[SAVER_KEY]# Store data to logf = open(self.log_file_name, 'a')if self.is_first_run:f.write('%s - FSize_watcher started. Monitoring file: %s, saving data period=%d sec\n' % (time.asctime(time.localtime()), lve_data[COLLECTOR_KEY_FILENAME], self.period))self.is_first_run = Falsef.write('%s - FSize_watcher: file size is %d bytes\n' % (time.asctime(time.localtime()), fsize))f.close()except:# Ignore all errorspass # Terminate handlerdef sigterm_handler(self, signum, frame):if self.log_file_name:try:# Store data to log filef = open(self.log_file_name, 'a')f.write('%s - File watcher saver plugin: TERMINATE\n' % time.asctime(time.localtime()))f.close()passexcept:# Ignore all errorspass# Terminate processsys.exit(0)
</code></pre>
<!--beforeend--></div><!--afterend--><p>Configuration file <em>/etc/sysconfig/lvestats.config/FSize_watcher_saver.cfg</em> :
<span class="notranslate"> </span></p>
<!--beforebegin--><div class="language- extra-class"><!--afterbegin--><pre v-pre class="language-text"><code># Config file for FSize_watcher_saver.py plugin# Please define log filename herelog_filename = /var/log/FSize_watcher.log
</code></pre>
<!--beforeend--></div><!--afterend--><p>This plugin starts after <span class="notranslate"> analyzer (order=2) </span> , checks new file size <span class="notranslate"> presence </span> flag, and if positive – writes it into log. If the flag is cleared (which means the size hasn't changed), then plugin simply ends.</p>
<p>Starts once in a minute (period=60).</p>
<p>Also this plugin shows the work of signal handler.</p>
<p>Plugin constructor registers handler-function of a proper signal: <span class="notranslate"> <em>signal.signal(signal.SIGTERM, self.sigterm_handler)</em> . </span> This means, that when the server finishes its work, then <span class="notranslate"> <em>sigterm_handler</em> </span> method of plugin class will be invoked. In the actual example the function just writes a notification into log, tracing the fact of it's invocation.</p>
<p>Pay attention on <span class="notranslate"> <em>sys.exit(0)</em> </span> command in the end of the handler. Find the information on it in <span class="notranslate"> <strong>Server Plugin Arrangement</strong> </span> section.</p>
<p>In addition see into examples of file log /var/log/FSize_watcher.log formed by the plugins above:
<span class="notranslate"> </span>
<em>Tue Feb 3 13:06:24 2015 - FSize_watcher started. Monitoring file: /usr/local/cpanel/logs/access_log, saving data period=60 sec</em>
<em>Tue Feb 3 13:06:24 2015 - FSize_watcher: file size is 122972890 bytes</em>
<em>Tue Feb 3 13:07:25 2015 - FSize_watcher: file size is 122975507 bytes</em>
<em>Tue Feb 3 13:08:25 2015 - FSize_watcher: file size is 122978124 bytes</em>
<em>Tue Feb 3 13:09:25 2015 - FSize_watcher: file size is 122978997 bytes</em>
<em>Tue Feb 3 13:10:25 2015 - FSize_watcher: file size is 122981033 bytes</em>
<em>Tue Feb 3 13:11:25 2015 - FSize_watcher: file size is 122982052 bytes</em>
<em>Tue Feb 3 13:13:25 2015 - FSize_watcher: file size is 122983798 bytes</em>
<em>Tue Feb 3 13:20:15 2015 - File watcher saver plugin: TERMINATE</em></p>
<p>and
<span class="notranslate"> </span>
<em>Thu Feb 5 13:07:27 2015 - FSize_watcher started. Monitoring file: /usr/local/cpanel/logs/error_log, saving data period=60 sec</em>
<em>Thu Feb 5 13:07:27 2015 - FSize_watcher: file size is 14771849 bytes</em>
<em>Thu Feb 5 14:03:32 2015 - FSize_watcher: file size is 14771995 bytes</em>
<em>Thu Feb 5 15:01:36 2015 - FSize_watcher: file size is 14772434 bytes</em>
<em>Thu Feb 5 17:15:47 2015 - FSize_watcher: file size is 14772873 bytes</em>
<em>Thu Feb 5 18:47:54 2015 - FSize_watcher: file size is 14775213 bytes</em>
<em>Thu Feb 5 19:11:56 2015 - FSize_watcher: file size is 14775652 bytes</em>
<em>Thu Feb 5 21:09:05 2015 - FSize_watcher: file size is 14776091 bytes</em>
<em>Thu Feb 5 23:06:14 2015 - FSize_watcher: file size is 14776530 bytes</em>
<em>Fri Feb 6 00:47:23 2015 - FSize_watcher: file size is 14778870 bytes</em>
<em>Fri Feb 6 01:02:24 2015 - FSize_watcher: file size is 14779309 bytes</em>
<em>Fri Feb 6 02:00:28 2015 - FSize_watcher: file size is 14779434 bytes</em>
<em>Fri Feb 6 03:16:34 2015 - FSize_watcher: file size is 14779873 bytes</em>
<em>Fri Feb 6 05:04:42 2015 - FSize_watcher: file size is 14779998 bytes</em>
<em>Fri Feb 6 05:12:43 2015 - FSize_watcher: file size is 14780437 bytes</em>
<em>Fri Feb 6 05:56:50 2015 - FSize_watcher: file size is 14780551 bytes</em>
<em>Fri Feb 6 06:01:50 2015 - FSize_watcher: file size is 14780975 bytes</em>
<em>Fri Feb 6 06:03:51 2015 - FSize_watcher: file size is 14782183 bytes</em>
<em>Fri Feb 6 06:04:51 2015 - FSize_watcher: file size is 14782575 bytes</em>
<em>Fri Feb 6 06:18:52 2015 - FSize_watcher: file size is 14782647 bytes</em>
<em>Fri Feb 6 06:21:52 2015 - FSize_watcher: file size is 14782898 bytes</em>
<em>Fri Feb 6 06:48:54 2015 - FSize_watcher: file size is 14785238 bytes</em>
<em>Fri Feb 6 07:09:56 2015 - FSize_watcher: file size is 14785677 bytes</em>
<em>Tue Feb 6 08:03:15 2015 - File watcher saver plugin: TERMINATE</em></p>
<p>You can see that log record is being held once a minute (what we actually need), new file size is written.</p>
<p>Also we can notice that handler <span class="notranslate"> SIG_TERM </span> was executed, signaling that plugin received the notification about server shut-down.</p>
<h4 id="notifier"><a class="header-anchor" href="#notifier" aria-hidden="true">#</a> Notifier</h4>
<p><span class="notranslate"> <strong>Notifier</strong> </span> informs system users about any events.
<span class="notranslate"> </span></p>
<!--beforebegin--><div class="language- extra-class"><!--afterbegin--><pre v-pre class="language-text"><code># FSize_watcher_saver.py# Example plugin for monitoring file size and last modification date-time.# Part 4. Notifier import timeimport smtplib from lvestats.lib.commons import dateutilfrom lvestats.core.plugin import LveStatsPlugin # Key nameCOLLECTOR_KEY_FSIZE = 'FSizeWatcher_fsize'COLLECTOR_KEY_FILENAME = 'FSizeWatcher_fname' # email message patternEMAIL_MESSAGE_PATTERN = """Hello, administrator!Size of the file '%s' is %d bytes.""" class FSize_watcher_notifier (LveStatsPlugin):# Default periodDEFAULT_PERIOD_STR = '12h'# this plugin should be third in chainorder = 3# Timeouttimeout = 20# Notifier Log filenamelog_file_name = '/var/log/FSize_watcher_notifier.log'# Email from addressemail_from = None# Email to addressemail_to = None# Email subjectemail_subject = None# Sets configuration to plugindef set_config(self, config):# Email settingsself.email_from = config.get('notify_from_email', None)self.email_to = config.get('notify_to_email', None)self.email_subject = config.get('notify_from_subject', 'Message from FSize_watcher_notifier plugin')# Notify periods_period = config.get('notify_period', None)if s_period:self.period = dateutil.parse_period2(s_period)else:self.period = dateutil.parse_period2(FSize_watcher_notifier.DEFAULT_PERIOD_STR)f = open(self.log_file_name, 'a')f.write('%s - FSize_watcher_notifier plugin: configure\n' % time.asctime(time.localtime()))f.write(' - Period: %s\n' % self.period)f.write(' - From: %s\n' % self.email_from)f.write(' - To: %s\n' % self.email_to)f.write(' - Subject: \'%s\'\n' % self.email_subject)f.close() # work methoddef execute(self, lve_data):if COLLECTOR_KEY_FSIZE not in lve_data or COLLECTOR_KEY_FILENAME not in lve_data:returnif not self.email_from or not self.email_to:f = open(self.log_file_name, 'a')f.write('%s - FSize_watcher_notifier plugin error: email_from or email_to not set\n')f.close()returntry:from email.mime.text import MIMEText# Send emailmsg = MIMEText(EMAIL_MESSAGE_PATTERN % (lve_data[COLLECTOR_KEY_FILENAME], lve_data[COLLECTOR_KEY_FSIZE]))msg['Subject'] = self.email_subjectmsg['From'] = self.email_frommsg['To'] = self.email_to s = smtplib.SMTP('localhost')s.sendmail(self.email_from, [self.email_to], msg.as_string())s.quit() f = open(self.log_file_name, 'a')f.write('%s - FSize_watcher_notifier plugin: email message was successfully sent\n' % time.asctime(time.localtime()))f.close()except Exception as e:f = open(self.log_file_name, 'a')f.write('%s - FSize_watcher_notifier plugin error:\n%s\n' % (time.asctime(time.localtime()), str(e)))f.close()
</code></pre>
<!--beforeend--></div><!--afterend--><p>Configuration file <em>/etc/sysconfig/lvestats.config/FSize_watcher_notifier.cfg</em> :
<span class="notranslate"> </span></p>
<!--beforebegin--><div class="language- extra-class"><!--afterbegin--><pre v-pre class="language-text"><code># Config file for FSize_watcher_notifier.py plugin# Please define email options here NOTIFY_FROM_EMAIL=user@hostnameNOTIFY_FROM_SUBJECT=Message from FSize_watcher_notifierNOTIFY_TO_EMAIL=admin@hostnameNOTIFY_PERIOD=12h
</code></pre>
<!--beforeend--></div><!--afterend--><p>Plugin’s index number equals 3 ( <span class="notranslate"> order=3 </span> ), that is why <span class="notranslate"> notifier </span> starts after the rest. But since it uses only data formed by <span class="notranslate"> collector </span> , then its order may equal any number bigger that <span class="notranslate"> collectors </span> order (>0).</p>
<p><span class="notranslate"> Notifier </span> reads the necessary parameters from the configuration (email address, topic, period) and writes them into its own log as reference.</p>
<p>Plugin’s <span class="notranslate"> <em>execute</em> </span> method checks the availability of all the necessary data (email parameters, collectors data) and sends the message. All the notifications are written into the <span class="notranslate"> notifier's </span> own log.</p>
<p>If any data is missing, the message is not sent.</p>
<p>Log example:
<span class="notranslate"> </span>
<em>Thu Feb 5 11:51:34 2015 - FSize_watcher_notifier plugin: configure</em>
_ - Period: 60.0_
_ - From: user@hostname_
_ - To: admin@hostname_
_ - Subject: 'Message from FSize_watcher_notifier'_
<em>Thu Feb 5 11:51:35 2015 - FSize_watcher_notifier plugin: email message was successfully sent</em>
<em>Thu Feb 5 11:52:35 2015 - FSize_watcher_notifier plugin: email message was successfully sent</em>
<em>Thu Feb 5 11:53:35 2015 - FSize_watcher_notifier plugin: email message was successfully sent</em>
<em>Thu Feb 5 11:54:35 2015 - FSize_watcher_notifier plugin: email message was successfully sent</em>
<em>Thu Feb 5 11:57:00 2015 - FSize_watcher_notifier plugin: configure</em>
_ - Period: 43200.0_
_ - From: user@hostname_
_ - To: admin@hostname_
_ - Subject: 'Message from FSize_watcher_notifier'_
<em>Thu Feb 5 11:57:00 2015 - FSize_watcher_notifier plugin: email message was successfully sent</em></p>
<h2 id="file-info-and-format-for-var-lve-info-file"><a class="header-anchor" href="#file-info-and-format-for-var-lve-info-file" aria-hidden="true">#</a> File info and format for /var/lve/info file</h2>
<p>This file is used by control panels to display to user their 'current' usage. The file is updated every 5 seconds by lve-stats.</p>
<p>When writing to this file we make sure that: average <span class="notranslate"> CPU/IOPS/MEM </span> is never more then <span class="notranslate"> LIMIT </span> for that resource.</p>
<p>Example:
<span class="notranslate"> </span>
0,0,20,0,2500,0,262144,0,0,262144,0,0,100,0,0,0,0,1024,1024,0,0,0,0
600,1,20,2492,2500,70,262144,0,0,262144,33,0,100,1,0,0,0,1024,1024,0,5,0,0
200,0,20,0,2500,0,262144,0,0,262144,0,0,100,0,0,0,0,1024,1024,0,0,0,0
500,0,20,0,2500,0,262144,0,0,262144,0,0,100,0,0,0,0,1024,1024,0,0,0,0</p>
<p>First line of the file is ' <span class="notranslate"> default limits </span> '.</p>
<p>Fields:</p>
<h1 id="_0-id"><a class="header-anchor" href="#_0-id" aria-hidden="true">#</a> 0 - id</h1>
<h1 id="_1-mep-average-entry-processes"><a class="header-anchor" href="#_1-mep-average-entry-processes" aria-hidden="true">#</a> 1 - mep (average entry processes)</h1>
<h1 id="_2-lep-limit"><a class="header-anchor" href="#_2-lep-limit" aria-hidden="true">#</a> 2 - lep (limit ...)</h1>
<h1 id="_3-cpu-usage-average-speed"><a class="header-anchor" href="#_3-cpu-usage-average-speed" aria-hidden="true">#</a> 3 - cpu_usage (average speed)</h1>
<h1 id="_4-lcpu-limit-spped"><a class="header-anchor" href="#_4-lcpu-limit-spped" aria-hidden="true">#</a> 4 - lcpu (limit spped)</h1>
<h1 id="_5-mem-usage-average-virtual-memory"><a class="header-anchor" href="#_5-mem-usage-average-virtual-memory" aria-hidden="true">#</a> 5 - mem_usage (average virtual memory)</h1>
<h1 id="_6-lmem-limit"><a class="header-anchor" href="#_6-lmem-limit" aria-hidden="true">#</a> 6 - lmem (limit ...)</h1>
<h1 id="_7-mem-fault-number-of-virtual-memory-faults"><a class="header-anchor" href="#_7-mem-fault-number-of-virtual-memory-faults" aria-hidden="true">#</a> 7 - mem_fault (number of virtual memory faults)</h1>
<h1 id="_8-mep-fault-number-of-entry-processes-faults"><a class="header-anchor" href="#_8-mep-fault-number-of-entry-processes-faults" aria-hidden="true">#</a> 8 - mep_fault (number of entry processes faults)</h1>
<p>LVE_VERSION >=6</p>
<h1 id="_9-lmemphy-limit-physical-memory"><a class="header-anchor" href="#_9-lmemphy-limit-physical-memory" aria-hidden="true">#</a> 9 - lmemphy (limit physical memory)</h1>
<h1 id="_10-memphy-average"><a class="header-anchor" href="#_10-memphy-average" aria-hidden="true">#</a> 10 - memphy (average ...)</h1>
<h1 id="_11-memphy-fault-faults"><a class="header-anchor" href="#_11-memphy-fault-faults" aria-hidden="true">#</a> 11 - memphy_fault (faults ...)</h1>
<h1 id="_12-lnproc-limit-number-of-processes"><a class="header-anchor" href="#_12-lnproc-limit-number-of-processes" aria-hidden="true">#</a> 12 - lnproc (limit number of processes)</h1>
<h1 id="_13-nproc-average"><a class="header-anchor" href="#_13-nproc-average" aria-hidden="true">#</a> 13 - nproc (average ...)</h1>
<h1 id="_14-nproc-fault-faults"><a class="header-anchor" href="#_14-nproc-fault-faults" aria-hidden="true">#</a> 14 - nproc_fault (faults ...)</h1>
<h1 id="_15-lcpuw-cpu-weight-deprecated-not-used"><a class="header-anchor" href="#_15-lcpuw-cpu-weight-deprecated-not-used" aria-hidden="true">#</a> 15 - lcpuw (CPU weight -- deprecated not used)</h1>
<h1 id="_16-io-usage-average-io-usage"><a class="header-anchor" href="#_16-io-usage-average-io-usage" aria-hidden="true">#</a> 16 - io_usage (average IO usage)</h1>
<h1 id="_17-io-limit-limit"><a class="header-anchor" href="#_17-io-limit-limit" aria-hidden="true">#</a> 17 - io_limit (limit ...)</h1>
<p>LVE_VERSION >=8
#18 - liops (limit IOPS)
#19 - iops (average IOPS)</p>
<h2 id="troubleshooting"><a class="header-anchor" href="#troubleshooting" aria-hidden="true">#</a> Troubleshooting</h2>
<p><span class="notranslate"> lvestats </span> service and utilities write fatal errors to system log.</p>
<p>There is _ /var/log/lve-stats.log_ file with additional information (warnings, tracebacks for errors)</p>
</div>
- tag <span> has no matching end tag.
@ ./docs/lve-stats_2/README.md?vue&type=template&id=65d90f0a& 1:0-457 1:0-457
@ ./docs/lve-stats_2/README.md
@ ./node_modules/vuepress/lib/app/.temp/routes.js
@ ./node_modules/vuepress/lib/app/app.js
@ ./node_modules/vuepress/lib/app/clientEntry.js
@ multi ./node_modules/vuepress/lib/app/clientEntry.js
ERROR in ./docs/node_js_selector/README.md?vue&type=template&id=35bc6d04& (./node_modules/cache-loader/dist/cjs.js?{"cacheDirectory":"node_modules/vuepress/node_modules/.cache/vuepress","cacheIdentifier":"18759c20-vue-loader-template"}!./node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!./node_modules/cache-loader/dist/cjs.js??ref--1-0!./node_modules/vue-loader/lib??ref--1-1!./node_modules/vuepress/lib/webpack/markdownLoader.js??ref--1-2!./docs/node_js_selector/README.md?vue&type=template&id=35bc6d04&)
Module Error (from ./node_modules/vue-loader/lib/loaders/templateLoader.js):
(Emitted value instead of an instance of Error)
Error compiling template:
<div class="content"><h1 id="node-js-selector"><a class="header-anchor" href="#node-js-selector" aria-hidden="true">#</a> Node.js Selector</h1>
<p><router-link to="/node_js_selector/#overview-requirements">Overview & Requirements</router-link>
<router-link to="/overview__requirements.html#requirements/">Requirements</router-link>
<router-link to="/node_js_selector/#installation">Installation</router-link>
<router-link to="/node_js_selector/#command-line-interface">Command Line Interface</router-link>
<router-link to="/command_line_interface2.html#hoster/">Hoster</router-link>
<router-link to="/command_line_interface2.html#enduser/">End User</router-link>
<router-link to="/node_js_selector/#user-interface">User Interface</router-link>
<router-link to="/user_interface.html#hoster/">Hoster</router-link>
<router-link to="/user_interface.html#howtoenabledisablenodejs/">How to enable/disable Node.js</router-link>
<router-link to="/user_interface.html#howtomanagenodejs/">How to manage Node.js</router-link>
<router-link to="/user_interface.html#applicationscolumn/">Applications column</router-link>
<router-link to="/user_interface.html#enduser/">End User</router-link>
<router-link to="/user_interface.html#howtomanageapplication/">How to manage application</router-link>
<router-link to="/node_js_selector/#node-js-deployment">Node.js Deployment</router-link>
<router-link to="/node_js_selector/#remote-usage-of-node-js-interpreters">Remote Usage of Node.js Interpreters</router-link>
<router-link to="/node_js_selector/#remote-usage-of-the-cloudlinux-selector-utility">Remote Usage of the cloudlinux-selector Utility</router-link></p>
<h2 id="overview-requirements"><a class="header-anchor" href="#overview-requirements" aria-hidden="true">#</a> Overview & Requirements</h2>
<p><span class="notranslate"> Node.js Selector <span class="notranslate"> is a CloudLinux component that allows each user to easily create Node.js applications, choose Node.js version and other parameters for applications based on their needs. </span> </span></p>
<p><span class="notranslate"> Node.js Selector <span class="notranslate"> supports Node.js versions 6.x, 8.x, 9.x and later. </span> </span>
This feature is available for CloudLinux 7, <span class="notranslate"> CloudLinux 6 hybrid <span class="notranslate"> and CloudLinux 6. </span> </span>
<span class="notranslate"> Node.js Selector <span class="notranslate"> requires <span class="notranslate"> LVE Manager 4.0 <span class="notranslate"> or later. </span> </span> </span> </span>
It supports cPanel and DirectAdmin servers (Plesk is not supported as it already has Node.js support.) For more details, please go to Plesk & Node.js documentation <a href="https://www.plesk.com/blog/product-technology/node-js-plesk-onyx/" target="_blank" rel="noopener noreferrer">here<OutboundLink/></a> and <a href="https://docs.plesk.com/en-US/onyx/administrator-guide/website-management/nodejs-support.76652/" target="_blank" rel="noopener noreferrer">here<OutboundLink/></a> .
For more details about <span class="notranslate"> mod_passenger <span class="notranslate"> and Node.js, please read documentation <a href="https://www.phusionpassenger.com/library/walkthroughs/deploy/nodejs/" target="_blank" rel="noopener noreferrer">here<OutboundLink/></a> and <a href="https://www.phusionpassenger.com/library/walkthroughs/deploy/nodejs/ownserver/apache/oss/el7/deploy_app.html" target="_blank" rel="noopener noreferrer">here<OutboundLink/></a> . </span> </span>
<span class="notranslate"> Node.js Selector <span class="notranslate"> is working with EasyApache 3 and EasyApache 4. </span> </span></p>
<h2 id="installation"><a class="header-anchor" href="#installation" aria-hidden="true">#</a> Installation</h2>
<p>To use Node.js Selector, please install Node.js packages by running the following command:</p>
<!--beforebegin--><div class="language- extra-class"><!--afterbegin--><pre v-pre class="language-text"><code>yum groupinstall alt-nodejs6 alt-nodejs8 alt-nodejs9
</code></pre>
<!--beforeend--></div><!--afterend--><p>Also, please install LVE Manager, LVE Utils and Fusion Passenger by running the following command:</p>
<!--beforebegin--><div class="language- extra-class"><!--afterbegin--><pre v-pre class="language-text"><code>yum install lvemanager lve-utils ea-apache24-mod-alt-passenger
</code></pre>
<!--beforeend--></div><!--afterend--><p>For EasyApache 3:</p>
<!--beforebegin--><div class="language- extra-class"><!--afterbegin--><pre v-pre class="language-text"><code>yum install lvemanager lve-utils alt-mod-passenger
</code></pre>
<!--beforeend--></div><!--afterend--><p>And we recommend to install CageFS for better security (not mandatory) by running the following command:</p>
<!--beforebegin--><div class="language- extra-class"><!--afterbegin--><pre v-pre class="language-text"><code>yum install cagefs
</code></pre>
<!--beforeend--></div><!--afterend--><p>CloudLinux 7:</p>
<!--beforebegin--><div class="language- extra-class"><!--afterbegin--><pre v-pre class="language-text"><code>systemctl restart cpanel.service
</code></pre>
<!--beforeend--></div><!--afterend--><p>CloudLinux 6:</p>
<!--beforebegin--><div class="language- extra-class"><!--afterbegin--><pre v-pre class="language-text"><code>service cpanel restart
</code></pre>
<!--beforeend--></div><!--afterend--><p>To use Node.js Selector, please install Node.js packages by running the following command:</p>
<!--beforebegin--><div class="language- extra-class"><!--afterbegin--><pre v-pre class="language-text"><code>yum groupinstall alt-nodejs6 alt-nodejs8 alt-nodejs9
</code></pre>
<!--beforeend--></div><!--afterend--><p>Also, please install LVE Manager, LVE Utils and Fusion Passenger by running the following command:</p>
<!--beforebegin--><div class="language- extra-class"><!--afterbegin--><pre v-pre class="language-text"><code>yum install lvemanager lve-utils alt-mod-passenger
</code></pre>
<!--beforeend--></div><!--afterend--><p>And we recommend to install CageFS for better security (not mandatory) by running the following command:</p>
<!--beforebegin--><div class="language- extra-class"><!--afterbegin--><pre v-pre class="language-text"><code>yum install cagefs
</code></pre>
<!--beforeend--></div><!--afterend--><h2 id="command-line-interface"><a class="header-anchor" href="#command-line-interface" aria-hidden="true">#</a> Command Line Interface</h2>
<p>Below is a list of commands hoster and end user can run in a command line.</p>
<p>Get information related to Node.js: default version, list of supported versions, status of <span class="notranslate"> Node.js Selector </span> , list of users, their applications, etc:
<span class="notranslate"> </span></p>
<!--beforebegin--><div class="language- extra-class"><!--afterbegin--><pre v-pre class="language-text"><code>cloudlinux-selector [get] [--json] --interpreter nodejs
</code></pre>
<!--beforeend--></div><!--afterend--><p><span class="notranslate"> JSON </span> output for <span class="notranslate"> <em>get</em> </span> command:
<span class="notranslate"> </span></p>
<!--beforebegin--><div class="language- extra-class"><!--afterbegin--><pre v-pre class="language-text"><code>{ "selector_enabled": true | false, "default_version": "6.11.3", "result": "success", "timestamp": 1508667174.220027 "cache_status": "ready" // or “updating” during automatic yum cache rebuild "available_versions": { // begin of “versions” "6.11.3" : { // begin of version "6.11.3" "name_modifier": "", "status": "enabled", // enabled, disabled, not_installed, installing, removing “base_dir”: “/opt/alt/alt-nodejs6” // empty when version is not installed “users”: { // begin of “users” “user1”: { // begin of “user1”“homedir”: “/home/user1”, “applications”: { // begin of “applications” “apps_dir/app1” : { // begin of application “apps_dir/app1” “domain”: “cltest1.com”, “app_uri”: “apps/my-app1”, “app_mode” : “development”, “startup_file” : “app.js”, “app_status” : “started”, // ‘started’ or ‘stopped’ “config_files” : [ “package.json”, “gruntfile.js” ], “env_vars” : { “var1” : “value1”, “var2” : “value2” }, }, // end of application “apps_dir/app1” “apps_dir/app2” : { // begin of application “apps_dir/app2” << data for application “apps_dir/app2” (same structure as for application “apps_dir/app1” above) >> }, // end of application “apps_dir/app2” }, // end of “applications” }, // end of “user1” “user2”: { // begin of “user2” << data for user “user2” (same structure as for “user1” above) >> }, // end of “user2” }, // end of “users” }, // end of version “6.11.3” "8.21.5" : { // begin of version "8.21.5" << data for version "8.21.5" (same structure as for version “6.11.3” above) >> }, // end of version “8.21.5” }, // end of “versions”} // end of json
</code></pre>
<!--beforeend--></div><!--afterend--><p>Set default version, supported versions, and status of <span class="notranslate"> Node.js Selector </span> :
<span class="notranslate"> </span></p>
<!--beforebegin--><div class="language- extra-class"><!--afterbegin--><pre v-pre class="language-text"><code>cloudlinux-selector set [--json] --interpreter nodejs (--selector-status <enabled,disabled> | --default-version <str> | --supported-versions <str>)
</code></pre>
<!--beforeend--></div><!--afterend--><p><strong>Note</strong> that <span class="notranslate"> Node.js Selector </span> is disabled by default. If an available Node.js version is not installed <span class="notranslate"> Node.js Selector </span> is always disabled and it is impossible to enable it.</p>
<p>To set default Node.js version, please use the following command (note that required Node.js version should be enabled):
<span class="notranslate"> </span></p>
<!--beforebegin--><div class="language- extra-class"><!--afterbegin--><pre v-pre class="language-text"><code>cloudlinux-selector set --json --interpreter=nodejs --default-version=<ver>
</code></pre>
<!--beforeend--></div><!--afterend--><p><strong>Examples</strong> :
This command enables <span class="notranslate"> Node.js Selector </span> :</p>
<p><span class="notranslate"> </span></p>
<!--beforebegin--><div class="language- extra-class"><!--afterbegin--><pre v-pre class="language-text"><code>cloudlinux-selector set --json --interpreter nodejs --selector-status enabled
</code></pre>
<!--beforeend--></div><!--afterend--><p>This command sets default Node.js version as 6:</p>
<p><span class="notranslate"> </span></p>
<!--beforebegin--><div class="language- extra-class"><!--afterbegin--><pre v-pre class="language-text"><code>cloudlinux-selector set --json --interpreter nodejs --default-version 6
</code></pre>
<!--beforeend--></div><!--afterend--><p>This command sets supported Node.js version as 8:
<span class="notranslate"> </span></p>
<!--beforebegin--><div class="language- extra-class"><!--afterbegin--><pre v-pre class="language-text"><code>cloudlinux-selector set --json --interpreter nodejs --supported-versions='{"6": false, "8": true}'
</code></pre>
<!--beforeend--></div><!--afterend--><p>Install required Node.js version:
<span class="notranslate"> </span></p>
<!--beforebegin--><div class="language- extra-class"><!--afterbegin--><pre v-pre class="language-text"><code>cloudlinux-selector install-version --json --interpreter nodejs --version 8
</code></pre>
<!--beforeend--></div><!--afterend--><p>Uninstall required Node.js version:
<span class="notranslate"> </span></p>
<!--beforebegin--><div class="language- extra-class"><!--afterbegin--><pre v-pre class="language-text"><code>cloudlinux-selector uninstall-version --json --interpreter nodejs --version 8
</code></pre>
<!--beforeend--></div><!--afterend--><p>Enable required Node.js version:
<span class="notranslate"> </span></p>
<!--beforebegin--><div class="language- extra-class"><!--afterbegin--><pre v-pre class="language-text"><code>cloudlinux-selector enable-version --json --interpreter nodejs --version 8
</code></pre>
<!--beforeend--></div><!--afterend--><p>Disable required Node.js version (note that it is impossible to disable default Node.js version):
<span class="notranslate"> </span></p>
<!--beforebegin--><div class="language- extra-class"><!--afterbegin--><pre v-pre class="language-text"><code>cloudlinux-selector disable-version --json --interpreter nodejs --version 8
</code></pre>
<!--beforeend--></div><!--afterend--><p>Change version for application(s):
<span class="notranslate"> </span></p>
<!--beforebegin--><div class="language- extra-class"><!--afterbegin--><pre v-pre class="language-text"><code>cloudlinux-selector set [--json] --interpreter nodejs ((--user <str> | --domain <str>) --app-root <str> | --from-version <str>) --new-version <str>
</code></pre>
<!--beforeend--></div><!--afterend--><p><strong>Examples</strong> :
This command changes version for the specific application:
<span class="notranslate"> </span></p>
<!--beforebegin--><div class="language- extra-class"><!--afterbegin--><pre v-pre class="language-text"><code>cloudlinux-selector set --json --interpreter nodejs --user user1 --app-root apps_dir/app1 --new-version 8
</code></pre>
<!--beforeend--></div><!--afterend--><p>Common output for all <span class="notranslate"> <em>set</em> </span> commands:</p>
<p><strong><em>in case of success</em></strong> :
<span class="notranslate"> </span></p>
<!--beforebegin--><div class="language- extra-class"><!--afterbegin--><pre v-pre class="language-text"><code>{ "result": "success", "timestamp": 1508666792.863358}
</code></pre>
<!--beforeend--></div><!--afterend--><p><strong><em>in case of error:</em></strong>
<span class="notranslate"> </span></p>
<!--beforebegin--><div class="language- extra-class"><!--afterbegin--><pre v-pre class="language-text"><code>{ "result": "Some error message", "details" : "Traceback: ..." , "context": {}, "timestamp": 1508666792.863358}
</code></pre>
<!--beforeend--></div><!--afterend--><p><strong><em>in case of warning:</em></strong>
<span class="notranslate"> </span></p>
<!--beforebegin--><div class="language- extra-class"><!--afterbegin--><pre v-pre class="language-text"><code>{ "result": "success", "warning" : "Some warning message" , "context": {}, "timestamp": 1508666792.863358}
</code></pre>
<!--beforeend--></div><!--afterend--><p>To resolve issues related to <span class="notranslate"> <em>install-version/uninstall-version</em> </span> commands (because they are running in the background) you may use this log file <span class="notranslate"> <em>/var/log/cl-nodejs-last-yum.log</em> </span>
It contains full <span class="notranslate"> <em>yum</em> </span> output from the <span class="notranslate"> <strong><em>latest</em></strong> </span> performed operation (install or uninstall) and it will be rewritten with each operation.</p>
<p>Get config file for the user applications</p>
<p><span class="notranslate"> </span></p>
<!--beforebegin--><div class="language- extra-class"><!--afterbegin--><pre v-pre class="language-text"><code>cloudlinux-selector read-config [--json] --interpreter nodejs [(--user <str> | --domain <str>)] --app-root <str> --config-file <name>
</code></pre>
<!--beforeend--></div><!--afterend--><p><span class="notranslate"> JSON </span> output:
<span class="notranslate"> </span></p>
<!--beforebegin--><div class="language- extra-class"><!--afterbegin--><pre v-pre class="language-text"><code>{ "result": "success", "timestamp": 1508666792.863358 "data": "content of config file as Base64 encoded string"}
</code></pre>
<!--beforeend--></div><!--afterend--><p><strong>Example</strong> :</p>
<p>This command gets config file for <span class="notranslate"> user1 </span> ’s application <span class="notranslate"> app1 </span> :
<span class="notranslate"> </span></p>
<!--beforebegin--><div class="language- extra-class"><!--afterbegin--><pre v-pre class="language-text"><code>cloudlinux-selector read-config --json --interpreter nodejs --user user1 --app-root app_dir/app1 --config-file package.json
</code></pre>
<!--beforeend--></div><!--afterend--><p>Save config file for the user applications
<span class="notranslate"> </span></p>
<!--beforebegin--><div class="language- extra-class"><!--afterbegin--><pre v-pre class="language-text"><code>cloudlinux-selector save-config [--json] --interpreter nodejs [(--user <str> | --domain <str>)] --app-root <str> --config-file <path> --content <content of config file as Base64 encoded string>
</code></pre>
<!--beforeend--></div><!--afterend--><p><span class="notranslate"> JSON </span> output (the same as for all <span class="notranslate"> <em>set</em> </span> commands):
<span class="notranslate"> </span></p>
<!--beforebegin--><div class="language- extra-class"><!--afterbegin--><pre v-pre class="language-text"><code>{ "result": "success", "timestamp": 1508666792.863358}
</code></pre>
<!--beforeend--></div><!--afterend--><h1 id="example-this-command-saves-config-file-for-user1-’s-application-app1"><a class="header-anchor" href="#example-this-command-saves-config-file-for-user1-’s-application-app1" aria-hidden="true">#</a> <strong>Example</strong> :
This command saves config file for <span class="notranslate"> user1 </span> ’s application <span class="notranslate"> app1 </span> :</h1>
<p><span class="notranslate"> </span></p>
<!--beforebegin--><div class="language- extra-class"><!--afterbegin--><pre v-pre class="language-text"><code>cloudlinux-selector save-config --json --interpreter nodejs --user user1 --app-root app_dir/app1 --config-file package.json --content VGh1ICAyIE5vdiAxMDo0MzoxMiBFRFQgMjAxNwo=
</code></pre>
<!--beforeend--></div><!--afterend--><p>Get a list of applications for the specific user
<span class="notranslate"> </span></p>
<!--beforebegin--><div class="language- extra-class"><!--afterbegin--><pre v-pre class="language-text"><code>cloudlinux-selector [get] [--json] --interpreter nodejs [(--user <str> | --domain <str>)]
</code></pre>
<!--beforeend--></div><!--afterend--><p><strong>Example</strong> :
This command gets a list of applications for the <span class="notranslate"> user1 </span> :
<span class="notranslate"> </span></p>
<!--beforebegin--><div class="language- extra-class"><!--afterbegin--><pre v-pre class="language-text"><code>cloudlinux-selector get --json --interpreter nodejs --user user1
</code></pre>
<!--beforeend--></div><!--afterend--><p>Create user application</p>
<p><span class="notranslate"> </span></p>
<!--beforebegin--><div class="language- extra-class"><!--afterbegin--><pre v-pre class="language-text"><code>cloudlinux-selector create [--json] --interpreter nodejs [(--user <str> | --domain <str>)] --app-root <str> --app-uri <str> [--version <str>] [--app-mode <str>] [--startup-file <str>] [--env-vars <json string>]
</code></pre>
<!--beforeend--></div><!--afterend--><p><strong>Example</strong> :
This command creates <span class="notranslate"> user1 </span> 's application for the domain <span class="notranslate"> xyz.com </span> :
<span class="notranslate"> </span></p>
<!--beforebegin--><div class="language- extra-class"><!--afterbegin--><pre v-pre class="language-text"><code>cloudlinux-selector create --json --interpreter nodejs --user user1 --app-root my_apps/app1 --app-uri apps/app1
</code></pre>
<!--beforeend--></div><!--afterend--><p>or
<span class="notranslate"> </span></p>
<!--beforebegin--><div class="language- extra-class"><!--afterbegin--><pre v-pre class="language-text"><code>cloudlinux-selector create --json --interpreter nodejs --app-root my_apps/app1 --domain xyz.com --app-uri apps/app1
</code></pre>
<!--beforeend--></div><!--afterend--><p>Start, restart, stop, and destroy user application
<span class="notranslate"> </span></p>
<!--beforebegin--><div class="language- extra-class"><!--afterbegin--><pre v-pre class="language-text"><code>cloudlinux-selector (start | restart | stop | destroy) [--json] --interpreter nodejs [(--user <str> | --domain <str>)] --app-root <str>
</code></pre>
<!--beforeend--></div><!--afterend--><p><strong>Example</strong> :
This command starts <span class="notranslate"> user1 </span> 's application:
<span class="notranslate"> </span></p>
<!--beforebegin--><div class="language- extra-class"><!--afterbegin--><pre v-pre class="language-text"><code>cloudlinux-selector start --json --interpreter nodejs --user user1 --app-root my_apps/app1
</code></pre>
<!--beforeend--></div><!--afterend--><p>Change properties for an application</p>
<!--beforebegin--><div class="language- extra-class"><!--afterbegin--><pre v-pre class="language-text"><code>
</code></pre>
<!--beforeend--></div><!--afterend--><p><strong>Example 1</strong> :
This command sets a production mode, new domain <span class="notranslate"> new.xyz.com </span> , new Node.js version 8, new <span class="notranslate"> URI </span> , new application <span class="notranslate"> root </span> directory and new startup file for <span class="notranslate"> user1 </span> application located on the domain <span class="notranslate"> xyz.com </span> :
<span class="notranslate"> </span></p>
<!--beforebegin--><div class="language- extra-class"><!--afterbegin--><pre v-pre class="language-text"><code>cloudlinux-selector set --json --interpreter nodejs --user user1 --app-root my_apps/app1 --mode production --new-app-root new_apps/new_app1 --new-domain new.xyz.com --new-app-uri new_apps/app1 --new-version 8 --startup-file new_app.js --env-vars '{ "var1" : "value1", "var2" : "value2" }'
</code></pre>
<!--beforeend--></div><!--afterend--><p><strong>Example 2</strong> :
<span class="notranslate"> </span></p>
<!--beforebegin--><div class="language- extra-class"><!--afterbegin--><pre v-pre class="language-text"><code>cloudlinux-selector set --json --interpreter nodejs --domain xyz.com --app-root my_apps/app1 --mode production --new-app-root new_apps/new_app1 --new-domain new.xyz.com --new-app-uri new_apps/app1 --new-version 8 --startup-file new_app.js --env-vars '{ "var1" : "value1", "var2" : "value2" }'
</code></pre>
<!--beforeend--></div><!--afterend--><p>Run <span class="notranslate"> <em>npm install</em> </span> command for the user application
<span class="notranslate"> </span></p>
<!--beforebegin--><div class="language- extra-class"><!--afterbegin--><pre v-pre class="language-text"><code>cloudlinux-selector install-modules [--json] --interpreter nodejs [(--user <str> | --domain <str>)] --app-root <str>
</code></pre>
<!--beforeend--></div><!--afterend--><p><strong>Example</strong> :
This command runs _ _ <span class="notranslate"> npm install </span> _ _ for <span class="notranslate"> user1 </span> application:</p>
<p><span class="notranslate"> </span></p>
<!--beforebegin--><div class="language- extra-class"><!--afterbegin--><pre v-pre class="language-text"><code>cloudlinux-selector install-modules --json --interpreter nodejs --user user1 --app-root my_apps/app
</code></pre>
<!--beforeend--></div><!--afterend--><p>Run a script from <span class="notranslate"> package.json </span> file of a user application, arguments <span class="notranslate"> <args> </span> are passed to the script
<span class="notranslate"> </span></p>
<!--beforebegin--><div class="language- extra-class"><!--afterbegin--><pre v-pre class="language-text"><code>cloudlinux-selector run-script [--json] --interpreter nodejs [(--user <str> | --domain <str>)] --app-root <str> --script-name <str> [-- <args>...]
</code></pre>
<!--beforeend--></div><!--afterend--><p><strong>Example</strong> :
<span class="notranslate"> </span></p>
<!--beforebegin--><div class="language- extra-class"><!--afterbegin--><pre v-pre class="language-text"><code>cloudlinux-selector run-script --json --interpreter nodejs --user user1 --app-root my_apps/app --script-name test_script -- --script_opt1 --script_opt2 script_arg1 script_arg2
</code></pre>
<!--beforeend--></div><!--afterend--><p><span class="notranslate"> JSON </span> output:</p>
<p><span class="notranslate"> </span></p>
<!--beforebegin--><div class="language- extra-class"><!--afterbegin--><pre v-pre class="language-text"><code>{ "result": "success", "timestamp": 1508666792.863358 "data": "script output as Base64 encoded string"}
</code></pre>
<!--beforeend--></div><!--afterend--><p>Activate virtual environment of NodeJS:
<span class="notranslate"> </span></p>
<!--beforebegin--><div class="language- extra-class"><!--afterbegin--><pre v-pre class="language-text"><code>source <home_of_user>/nodevenv/<app_root>/<nodejs_version>/bin/activate
</code></pre>
<!--beforeend--></div><!--afterend--><p>This command changes prompt to
<strong>Example</strong> :
<span class="notranslate"> </span></p>
<!--beforebegin--><div class="language- extra-class"><!--afterbegin--><pre v-pre class="language-text"><code>[newusr@192-168-245-108 ~]$ source /home/newusr/nodevenv/newapp4/newapp3/8/bin/activate[newapp4/newapp3 (8)] [newusr@192-168-245-108 ~]$
</code></pre>
<!--beforeend--></div><!--afterend--><p>After ativation user can use <span class="notranslate"> <em>npm</em> </span> and node from a virtual environment without full paths.</p>
<h2 id="user-interface"><a class="header-anchor" href="#user-interface" aria-hidden="true">#</a> User Interface</h2>
<p>Hoster interface allows to enable and disable Node.js, and manage individual Node.js versions.</p>
<p>Go to <span class="notranslate"> <em>LVE Manager → Options Tab → Node.js Section</em> </span> . A list of installed Node.js versions is displayed. There are several columns in the list.</p>
<p><span class="notranslate"> Version </span> — displays Node.js version.
<span class="notranslate"> Path </span> — Node.js package location.
<span class="notranslate"> Applications </span> — number of applications that use this Node.js version. Click on a digit to go to the list of applications.
<span class="notranslate"> Enabled </span> — displays if particular Node.js version is enabled.
<span class="notranslate"> Actions </span> — allows to install, delete, and make default a particular Node.js version.
To display all changes immediately click <span class="notranslate"> <em>Refresh</em> </span> link.</p>
<p><img src="/images/nodejsgeneral_zoom70.png" alt=""></p>
<p>To enable Node.js move a slider to <span class="notranslate"> <em>Enable</em> </span> .
To disable Node.js move a slider back to <span class="notranslate"> <em>Disable</em> </span> .</p>
<p><img src="/images/nodejsslider_zoom70.png" alt=""></p>
<p><img src="/images/nodejsselectorlogo_zoom70.png" alt=""></p>
<p>The list of installed Node.js versions allows to enable and disable, install and delete, and set a particular Node.js version as a default.</p>
<p><strong>Enable and disable particular Node.js version</strong></p>
<p>To enable particular Node.js version do the following:
Move a disabled slider in the <span class="notranslate"> <em>Enabled</em> </span> column for a particular Node.js version.
In the confirmation pop-up click <span class="notranslate"> <em>Agree</em> </span> to save changes or <span class="notranslate"> <em>Cancel</em> </span> to close pop-up.</p>
<p><img src="/images/nodejsenable_zoom70.png" alt=""></p>
<p>To disable particular Node.js version do the following:
Move an enabled slider in the <span class="notranslate"> <em>Enabled</em> </span> column for a particular Node.js version.
In the confirmation pop-up click <span class="notranslate"> <em>Agree</em> </span> to save changes or <span class="notranslate"> <em>Cancel</em> </span> to close pop-up.</p>
<p><strong>Install and delete particular Node.js version</strong></p>
<p>To install particular Node.js version do the following:
Click <span class="notranslate"> <em>Install</em> </span> button in the <span class="notranslate"> <em>Actions</em> </span> column for a particular Node.js version.
In the confirmation pop-up click <span class="notranslate"> <em>Agree</em> </span> to save changes or <span class="notranslate"> <em>Cancel</em> </span> to close pop-up.</p>
<p>To delete particular Node.js version do the following:
Click <span class="notranslate"> <em>Bin</em> </span> icon in the <span class="notranslate"> <em>Actions</em> </span> column for a particular Node.js version.
In the confirmation pop-up click <span class="notranslate"> <em>Agree</em> </span> to start uninstall process.
Or close a pop-up without changes.</p>
<p><strong>Note that it is impossible</strong> :
to remove default Node.js version;
to remove version with applications;
to install or remove version if another installation/uninstall process is running.</p>
<p><img src="/images/nodejsconfirmation_zoom70.png" alt=""></p>
<p><strong>Make a particular Node.js version as a default</strong></p>
<p>To make a particular Node.js version as a default do the following:
Click <span class="notranslate"> <em>Double-Tick</em> </span> icon in the <span class="notranslate"> <em>Actions</em> </span> column for a particular Node.js version.
In the confirmation pop-up click <span class="notranslate"> <em>Agree</em> </span> to save changes or <span class="notranslate"> <em>Cancel</em> </span> to close pop-up.</p>
<p><img src="/images/nodejsmakedefault_zoom70.png" alt=""></p>
<p>To view and operate with the list of domains with Node.js versions click on a number in the <span class="notranslate"> <em>Applications</em> </span> column for a particular Node.js version. A section with a list of Domains for particular Node.js version will be displayed.</p>
<p><img src="/images/nodejsselectordomains_zoom70.png" alt=""></p>
<p>Domains are displayed by three. To load more domains click on <span class="notranslate"> <em>Load More</em> </span> button.</p>
<p>To change Node.js version for a particular application do the following:
Click <span class="notranslate"> <em>Double-Arrow</em> </span> icon in the <span class="notranslate"> <em>Actions</em> </span> column in a particular application row. A confirmation pop-up will be displayed.
In the pop-up choose Node.js version from a drop-down.
Click <span class="notranslate"> <em>Change</em> </span> to confirm the action or <span class="notranslate"> <em>Cancel</em> </span> to close the pop-up.
To refresh state of applications in current version you can click <span class="notranslate"> <em>Refresh</em> </span> link.</p>
<p><strong>Note</strong> that <span class="notranslate"> Node.js Selector </span> icon in end user interface is absent when Node.js is disabled.</p>
<p><img src="/images/nodejslogoenduser_zoom70.png" alt=""></p>
<p>End User interface allows end users to setup and manage Node.js for their web applications.
Go to <span class="notranslate"> <em>cPanel → Software Section → Select Node.js Version</em> </span> .</p>
<p><span class="notranslate"> <em>Web Applications</em> </span> page is displayed.</p>
<p><img src="/images/nodejsusermain_zoom70.png" alt=""></p>
<p>There are several columns in the list.
<span class="notranslate"> App URI </span> — application URI including the domain.
<span class="notranslate"> App Root Directory </span> — application root directory relative to user's home.
<span class="notranslate"> Mode </span> — can be production or development.
<span class="notranslate"> Status </span> — started/stopped — displays if an application is running or not and version of application.
<span class="notranslate"> Actions </span> — allows to start, restart, stop, edit, and remove a particular application.</p>
<p><strong>Start application</strong></p>
<p>To start a stopped application do the following:
Click <span class="notranslate"> <em>Start</em> </span> icon in the <span class="notranslate"> <em>Actions</em> </span> column in a stopped application row.
When an action is completed a <span class="notranslate"> <em>Start</em> </span> icon changes to <span class="notranslate"> <em>Stop</em> </span> icon.</p>
<p><strong>Stop application</strong></p>
<p>To stop a started application do the following:
Click <span class="notranslate"> <em>Stop</em> </span> icon in the <span class="notranslate"> <em>Actions</em> </span> column in a started application row.
When an action is completed a <span class="notranslate"> <em>Stop</em> </span> icon changes to <span class="notranslate"> <em>Start</em> </span> icon.</p>
<p><img src="/images/nodejsuseruistartstop_zoom70.png" alt=""></p>
<p><strong>Restart application</strong></p>
<p>To restart started application do the following:
Click <span class="notranslate"> <em>Restart</em> </span> icon in the <span class="notranslate"> <em>Actions</em> </span> column in a started application row. A current row is blocked and when a process is completed it will be unblocked.</p>
<p><strong>Remove application</strong></p>
<p>To remove application do the following:
Click <span class="notranslate"> <em>Bin</em> </span> icon in the <span class="notranslate"> <em>Actions</em> </span> column in a particular application row.
In the confirmation pop-up click <span class="notranslate"> <em>Agree</em> </span> to start removing or <span class="notranslate"> <em>Cancel</em> </span> to close pop-up.
When an action is completed an application will be removed from the <span class="notranslate"> <em>Web Applications</em> </span> table and a confirmation pop-up will be displayed.</p>
<p><img src="/images/nodejsuseruirestartremove_zoom70.png" alt=""></p>
<p><strong>Edit application</strong></p>
<p>To edit application do the following:
Click <span class="notranslate"> <em>Pencil</em> </span> icon in the <span class="notranslate"> <em>Actions</em> </span> column in a particular application row. A particular application tab opens.</p>
<p><img src="/images/nodejseditapp_zoom70.png" alt=""></p>
<p>The following actions are available:
Restart application — click <span class="notranslate"> <em>Restart</em> </span> button.
Stop Node.js — click <span class="notranslate"> <em>Stop Node.js</em> </span> button.
Run JavaScript script — click <span class="notranslate"> <em>Run JS Script</em> </span> button to run a command specified in the <span class="notranslate"> Scripts </span> section of the package.json file. Specify the name of the script to run plus any parameters then click <span class="notranslate"> Ok </span> .
Remove application — click <span class="notranslate"> <em>Delete</em> </span> button and confirm the action in a pop-up.
Change Node.js version — choose Node.js version from a drop-down.
Change Application mode — choose application mode from a drop-down. Available modes are <span class="notranslate"> <em>Production</em> </span> and <span class="notranslate"> <em>Development</em> </span> .
Specify Application root — specify in a field a physical address to the application on a server that corresponds with its URI.
Specify Application URL — specify in a field an HTTP/HTTPS link to the application.
Specify Application startup file — specify as <span class="notranslate"> NAME.js file </span> .
Run npm install command — click <span class="notranslate"> <em>Run npm install</em> </span> button to install the package(s) described in the <span class="notranslate"> package.json </span> file.
Add Environment variables — click <span class="notranslate"> <em>Add Variable</em> </span> and specify a name and a value.</p>
<h2 id="node-js-deployment"><a class="header-anchor" href="#node-js-deployment" aria-hidden="true">#</a> Node.js Deployment</h2>
<p>The first approach - <router-link to="/node_js_selector/#remote-usage-of-node-js-interpreters">remote usage of Node.js Interpreters of different versions</router-link> .
The second approach - <router-link to="/node_js_selector/#remote-usage-of-the-cloudlinux-selector-utility">remote usage of the </router-link> <span class="notranslate"> <router-link to="/node_js_selector/#remote-usage-of-the-cloudlinux-selector-utility">cloudlinux-selector utility</router-link> </span> .</p>
<h3 id="remote-usage-of-node-js-interpreters"><a class="header-anchor" href="#remote-usage-of-node-js-interpreters" aria-hidden="true">#</a> Remote Usage of Node.js Interpreters</h3>
<ol>
<li>Create a Node.js project in <span class="notranslate"> IntelliJ IDEA/WebStorm </span> . You can download <a href="http://docs.cloudlinux.com/nodejs_example.zip" target="_blank" rel="noopener noreferrer">this archive<OutboundLink/></a> and use it as a basis.</li>
<li>Install <span class="notranslate"> alt-nodejs </span> packages on the server in use. See <router-link to="/node_js_selector/#installation">installation instructions</router-link> .</li>
<li>Create an application on the server. You can do it by three ways:
Via UI of the Node.js plugin.
Using the following command to create an application:
<span class="notranslate"> </span></li>
</ol>
<!--beforebegin--><div class="language- extra-class"><!--afterbegin--><pre v-pre class="language-text"><code>cloudlinux-selector create --interprete=nodejs --json --app-root=<USER_NAME> --app-uri=<APP_NAME> --app-mode=develompent --version=<VERSION> --domain=<DOMAIN>
</code></pre>
<!--beforeend--></div><!--afterend--><p><img src="/images/createapp_zoom70.png" alt=""></p>
<p>Choose a location of the application on the server and synchronize the files with the <span class="notranslate"> IntelliJ IDEA </span> project.
4. Set up <span class="notranslate"> Run/Debug Configurations </span> in the project created.</p>
<p><img src="/images/setconfiguration_zoom70.png" alt=""></p>
<p>Specify a path to the remote Node.js interpreter. To be able to specify the remote interpreter, you should install the <span class="notranslate"> <em>Node.js Remote Interpreter</em> </span> plugin first. Please find more information <a href="https://www.jetbrains.com/help/idea/configure-node-js-remote-interpreter.html" target="_blank" rel="noopener noreferrer">here<OutboundLink/></a> , using server access credentials for a user <span class="notranslate"> (Main menu — Run — Edit configurations...) </span> .
Specify initial <em>JavaScript file</em> that will be run with the <span class="notranslate"> <em>node</em> </span> command (it is the <em>app.js</em> file from the archive).
Specify <span class="notranslate"> <em>Path Mappings</em> </span> between a local and a remote project <span class="notranslate"> (Preferences — Deployments — Add) </span> . If you have created your application with the <span class="notranslate"> <em>cloudlinux-selector utility</em> </span> or via plugin UI the <span class="notranslate"> <em>Path Mappings</em> </span> should be as follows:
<span class="notranslate"> </span></p>
<!--beforebegin--><div class="language- extra-class"><!--afterbegin--><pre v-pre class="language-text"><code>/home/<USER_NAME>/<APP_NAME>
</code></pre>
<!--beforeend--></div><!--afterend--><ol start="5">
<li>Synchronize the project directories on the local and the remote machine as per <span class="notranslate"> <em>Path Mappings</em> </span> specified.</li>
<li>Deploy the modules on the remote and the local machine with the <span class="notranslate"> <strong><em>npm install</em></strong> </span> command (if there are dependent modules). In the UI you can click the <span class="notranslate"> <em>Run NPM Install</em> </span> button.</li>
<li>Run Node.js application with the configuration set at the <router-link to="/remote_usage_of_node_js_interp.html#setuprundebugconfigurations/">4th step</router-link> <span class="notranslate"> (Main menu — Run — Run… — Select configuration) </span> .</li>
</ol>
<p><img src="/images/runapp_zoom60.png" alt=""></p>
<ol start="8">
<li>If you are using the application from the archive attached, you can see the running application on the 3003 port — <span class="notranslate"> <em>http://DOMAIN:3003</em> . </span></li>
</ol>
<p><strong>Note.</strong> The port should be available to a server user.</p>
<p><img src="/images/runningappdomain_zoom70.png" alt=""></p>
<p>The following information should be displayed on this page:
A version of the running Node.js interpreter;
Current environment variables;
A current time.
So that, you can be sure that deployed modules are used properly.</p>
<p>If you’d like to use a different version of Node.js to run an application, change a path to the interpreter in the configuration settings of the running.
To apply all changes to the project, synchronize all changes with the server and restart the running application.</p>
<ol start="9">
<li>To debug a script, set breakpoints in the code and run the configuration via Main Menu <span class="notranslate"> (Main menu — Run — Debug… — Select configuration) </span> .</li>
</ol>
<p>Useful links:
<span class="notranslate"> IntelliJ IDEA </span> : <a href="https://www.jetbrains.com/help/idea/configure-node-js-remote-interpreter.html" target="_blank" rel="noopener noreferrer">https://www.jetbrains.com/help/idea/configure-node-js-remote-interpreter.html<OutboundLink/></a>
Plugin <span class="notranslate"> <em>Node.js Remote Interpreter</em> </span> : <a href="https://plugins.jetbrains.com/plugin/8116-node-js-remote-interpreter" target="_blank" rel="noopener noreferrer">https://plugins.jetbrains.com/plugin/8116-node-js-remote-interpreter<OutboundLink/></a>
<span class="notranslate"> WebStorm </span> : <a href="https://www.jetbrains.com/help/webstorm/configure-node-js-remote-interpreter.html" target="_blank" rel="noopener noreferrer">https://www.jetbrains.com/help/webstorm/configure-node-js-remote-interpreter.html<OutboundLink/></a></p>
<p><strong>Note.</strong> It is not required to install <span class="notranslate"> <em>Passenger</em> </span> while working in <span class="notranslate"> IDE </span> if you are using this approach.</p>
<h3 id="remote-usage-of-the-cloudlinux-selector-utility"><a class="header-anchor" href="#remote-usage-of-the-cloudlinux-selector-utility" aria-hidden="true">#</a> Remote Usage of the cloudlinux-selector Utility</h3>
<p>Create an application via UI or with the command as described in the Remote Usage of Node.js Interpreters approach, <router-link to="/remote_usage_of_node_js_interp.html#createapplication/">step 3 (a,b)</router-link> .
2. Set up project mapping on the local machine with the created remote application _ _ <span class="notranslate"> /home/<USER_NAME>/<APP_NAME> </span> _ (Preferences → Deployments → Add)_ .
3. Set up the remote commands of the <span class="notranslate"> cloudlinux-selector (Preferences → Remote SSH External Tools → Add) </span> for the following actions:
Restart application;
Install packages;
Run script;
Change Node.js version for the application.
You can see the running app at <span class="notranslate"> http://DOMAIN/APPLICATION_URL </span>
To apply all changes, restart the application.</p>
</div>
- tag <args> has no matching end tag.
@ ./docs/node_js_selector/README.md?vue&type=template&id=35bc6d04& 1:0-457 1:0-457
@ ./docs/node_js_selector/README.md
@ ./node_modules/vuepress/lib/app/.temp/routes.js
@ ./node_modules/vuepress/lib/app/app.js
@ ./node_modules/vuepress/lib/app/clientEntry.js
@ multi ./node_modules/vuepress/lib/app/clientEntry.js
Child html-webpack-plugin for "index.html":
Asset Size Chunks Chunk Names
index.html 1.38 MiB 0
Entrypoint undefined = index.html
[./node_modules/lodash/lodash.js] 527 KiB {0} [built]
[./node_modules/vuepress-html-webpack-plugin/lib/loader.js!./node_modules/vuepress/lib/app/index.dev.html] 421 bytes {0} [built]
[./node_modules/webpack/buildin/module.js] (webpack)/buildin/module.js 497 bytes {0} [built]