rev |
line source |
devi@23
|
1 #!/usr/bin/perl -w
|
devi@23
|
2
|
devi@31
|
3 use IO::Socket;
|
devi@23
|
4 use lib '.';
|
devi@23
|
5 use l3config;
|
devi@31
|
6 use locale;
|
devi@23
|
7
|
devi@23
|
8 our @Command_Lines;
|
devi@31
|
9 our @Command_Lines_Index;
|
devi@31
|
10 our %Commands_Description;
|
devi@31
|
11 our %Args_Description;
|
devi@31
|
12 our $Mywi_Socket;
|
devi@32
|
13 our %Sessions;
|
devi@23
|
14
|
devi@23
|
15 # vvv Инициализация переменных выполняется процедурой init_variables
|
devi@23
|
16 our @Day_Name;
|
devi@23
|
17 our @Month_Name;
|
devi@23
|
18 our @Of_Month_Name;
|
devi@23
|
19 our %Search_Machines;
|
devi@23
|
20 our %Elements_Visibility;
|
devi@23
|
21 # ^^^
|
devi@23
|
22
|
devi@31
|
23 our %Stat;
|
devi@49
|
24 our %CommandsFDistribution; # Сколько раз в журнале встречается какая команда
|
devi@31
|
25
|
devi@55
|
26 my %mywi_cache_for; # Кэш для экономии обращений к mywi
|
devi@55
|
27
|
devi@55
|
28
|
devi@23
|
29 sub search_buy;
|
devi@23
|
30 sub make_comment;
|
devi@23
|
31 sub load_command_lines_from_xml;
|
devi@32
|
32 sub load_sessions_from_xml;
|
devi@23
|
33 sub print_command_lines;
|
devi@31
|
34 sub sort_command_lines;
|
devi@31
|
35 sub process_command_lines;
|
devi@23
|
36 sub init_variables;
|
devi@23
|
37 sub main;
|
devi@31
|
38 sub collapse_list($);
|
devi@23
|
39
|
devi@23
|
40 main();
|
devi@23
|
41
|
devi@23
|
42 sub main
|
devi@23
|
43 {
|
devi@49
|
44 $| = 1;
|
devi@23
|
45
|
devi@49
|
46 init_variables();
|
devi@49
|
47 init_config();
|
devi@23
|
48
|
devi@49
|
49 open_mywi_socket();
|
devi@49
|
50 load_command_lines_from_xml($Config{"backend_datafile"});
|
devi@49
|
51 load_sessions_from_xml($Config{"backend_datafile"});
|
devi@49
|
52 sort_command_lines;
|
devi@49
|
53 process_command_lines;
|
devi@49
|
54 print_command_lines($Config{"output"});
|
devi@49
|
55 close_mywi_socket;
|
devi@23
|
56 }
|
devi@23
|
57
|
devi@23
|
58
|
devi@23
|
59 sub search_by
|
devi@23
|
60 {
|
devi@49
|
61 my $sm = shift;
|
devi@49
|
62 my $topic = shift;
|
devi@49
|
63 $topic =~ s/ /+/;
|
devi@49
|
64
|
devi@49
|
65 return "<a href='". $Search_Machines{$sm}->{"query"}."$topic'><img width='16' height='16' src='".
|
devi@49
|
66 $Search_Machines{$sm}->{"icon"}."' border='0'/></a>";
|
devi@23
|
67 }
|
devi@23
|
68
|
devi@31
|
69 sub extract_from_cline
|
devi@31
|
70 # Разобрать командную строку $_[1] и возвратить хэш, содержащий
|
devi@31
|
71 # номер первого появление команды в строке:
|
devi@49
|
72 # команда => первая позиция
|
devi@31
|
73 {
|
devi@49
|
74 my $what = $_[0];
|
devi@49
|
75 my $cline = $_[1];
|
devi@49
|
76 my @lists = split /\;/, $cline;
|
devi@49
|
77
|
devi@49
|
78
|
devi@49
|
79 my @commands = ();
|
devi@49
|
80 for my $list (@lists) {
|
devi@49
|
81 push @commands, split /\|/, $list;
|
devi@49
|
82 }
|
devi@31
|
83
|
devi@49
|
84 my %commands;
|
devi@49
|
85 my %args;
|
devi@49
|
86 my $i=0;
|
devi@49
|
87 for my $command (@commands) {
|
devi@49
|
88 $command =~ s@^\s*\S+/@@;
|
devi@49
|
89 $command =~ /\s*(\S+)\s*(.*)/;
|
devi@49
|
90 if ($1 && $1 eq "sudo" ) {
|
devi@49
|
91 $commands{"$1"}=$i++;
|
devi@49
|
92 $command =~ s/\s*sudo\s+//;
|
devi@49
|
93 }
|
devi@49
|
94 $command =~ s@^\s*\S+/@@;
|
devi@49
|
95 $command =~ /\s*(\S+)\s*(.*)/;
|
devi@49
|
96 if ($1 && !defined $commands{"$1"}) {
|
devi@49
|
97 $commands{"$1"}=$i++;
|
devi@49
|
98 };
|
devi@49
|
99 if ($2) {
|
devi@49
|
100 my $args = $2;
|
devi@49
|
101 my @args = split (/\s+/, $args);
|
devi@49
|
102 for my $a (@args) {
|
devi@49
|
103 $args{"$a"}=$i++
|
devi@49
|
104 if !defined $args{"$a"};
|
devi@49
|
105 };
|
devi@31
|
106
|
devi@49
|
107
|
devi@49
|
108 }
|
devi@49
|
109 }
|
devi@31
|
110
|
devi@49
|
111 if ($what eq "commands") {
|
devi@49
|
112 return \%commands;
|
devi@49
|
113 } else {
|
devi@49
|
114 return \%args;
|
devi@49
|
115 }
|
devi@49
|
116
|
devi@31
|
117 }
|
devi@31
|
118
|
devi@31
|
119 sub open_mywi_socket
|
devi@31
|
120 {
|
devi@49
|
121 $Mywi_Socket = IO::Socket::INET->new(
|
devi@49
|
122 PeerAddr => $Config{mywi_server},
|
devi@49
|
123 PeerPort => $Config{mywi_port},
|
devi@49
|
124 Proto => "tcp",
|
devi@49
|
125 Type => SOCK_STREAM);
|
devi@31
|
126 }
|
devi@31
|
127
|
devi@31
|
128 sub close_mywi_socket
|
devi@31
|
129 {
|
devi@52
|
130 close ($Mywi_Socket) if $Mywi_Socket ;
|
devi@31
|
131 }
|
devi@31
|
132
|
devi@31
|
133
|
devi@31
|
134 sub mywi_client
|
devi@31
|
135 {
|
devi@49
|
136 my $query = $_[0];
|
devi@49
|
137 my $mywi;
|
devi@31
|
138
|
devi@49
|
139 open_mywi_socket;
|
devi@49
|
140 if ($Mywi_Socket) {
|
devi@49
|
141 local $| = 1;
|
devi@49
|
142 local $/ = "";
|
devi@49
|
143 print $Mywi_Socket $query."\n";
|
devi@49
|
144 $mywi = <$Mywi_Socket>;
|
devi@49
|
145 $mywi = "" if $mywi =~ /nothing app/;
|
devi@49
|
146 }
|
devi@49
|
147 close_mywi_socket;
|
devi@49
|
148 return $mywi;
|
devi@31
|
149 }
|
devi@31
|
150
|
devi@23
|
151 sub make_comment
|
devi@23
|
152 {
|
devi@49
|
153 my $cline = $_[0];
|
devi@49
|
154 #my $files = $_[1];
|
devi@23
|
155
|
devi@55
|
156 my @comments;
|
devi@49
|
157 my @commands = keys %{extract_from_cline("commands", $cline)};
|
devi@49
|
158 my @args = keys %{extract_from_cline("args", $cline)};
|
devi@49
|
159 return if (!@commands && !@args);
|
devi@49
|
160 #return "commands=".join(" ",@commands)."; files=".join(" ",@files);
|
devi@23
|
161
|
devi@49
|
162 # Commands
|
devi@49
|
163 for my $command (@commands) {
|
devi@49
|
164 $command =~ s/'//g;
|
devi@49
|
165 $CommandsFDistribution{$command}++;
|
devi@49
|
166 if (!$Commands_Description{$command}) {
|
devi@55
|
167 $mywi_cache_for{$command} ||= mywi_client ($command) || "";
|
devi@55
|
168 my $mywi = join ("\n", grep(/\([18]\)/, split(/\n/, $mywi_cache_for{$command})));
|
devi@49
|
169 $mywi =~ s/\s+/ /;
|
devi@49
|
170 if ($mywi !~ /^\s*$/) {
|
devi@49
|
171 $Commands_Description{$command} = $mywi;
|
devi@49
|
172 }
|
devi@49
|
173 else {
|
devi@49
|
174 next;
|
devi@49
|
175 }
|
devi@49
|
176 }
|
devi@23
|
177
|
devi@49
|
178 push @comments, $Commands_Description{$command};
|
devi@49
|
179 }
|
devi@49
|
180 return join(" \n", @comments);
|
devi@49
|
181
|
devi@49
|
182 # Files
|
devi@49
|
183 for my $arg (@args) {
|
devi@49
|
184 $arg =~ s/'//g;
|
devi@49
|
185 if (!$Args_Description{$arg}) {
|
devi@49
|
186 my $mywi;
|
devi@49
|
187 $mywi = mywi_client ($arg);
|
devi@49
|
188 $mywi = join ("\n", grep(/\([5]\)/, split(/\n/, $mywi)));
|
devi@49
|
189 $mywi =~ s/\s+/ /;
|
devi@49
|
190 if ($mywi !~ /^\s*$/) {
|
devi@49
|
191 $Args_Description{$arg} = $mywi;
|
devi@49
|
192 }
|
devi@49
|
193 else {
|
devi@49
|
194 next;
|
devi@49
|
195 }
|
devi@49
|
196 }
|
devi@23
|
197
|
devi@49
|
198 push @comments, $Args_Description{$arg};
|
devi@49
|
199 }
|
devi@23
|
200
|
devi@23
|
201 }
|
devi@23
|
202
|
devi@23
|
203 =cut
|
devi@23
|
204 Процедура load_command_lines_from_xml выполняет загрузку разобранного lab-скрипта
|
devi@23
|
205 из XML-документа в переменную @Command_Lines
|
devi@23
|
206
|
devi@23
|
207 Предупреждение!
|
devi@23
|
208 Процедура не в состоянии обрабатывать XML-документ любой структуры.
|
devi@23
|
209 В действительности файл cache из которого загружаются данные
|
devi@23
|
210 просто напоминает XML с виду.
|
devi@23
|
211 =cut
|
devi@23
|
212 sub load_command_lines_from_xml
|
devi@23
|
213 {
|
devi@49
|
214 my $datafile = $_[0];
|
devi@23
|
215
|
devi@49
|
216 open (CLASS, $datafile)
|
devi@49
|
217 or die "Can't open file of the class ",$datafile,"\n";
|
devi@49
|
218 local $/;
|
devi@49
|
219 $data = <CLASS>;
|
devi@49
|
220 close(CLASS);
|
devi@23
|
221
|
devi@49
|
222 for $command ($data =~ m@<command>(.*?)</command>@sg) {
|
devi@49
|
223 my %cl;
|
devi@49
|
224 while ($command =~ m@<([^>]*?)>(.*?)</\1>@sg) {
|
devi@49
|
225 $cl{$1} = $2;
|
devi@49
|
226 }
|
devi@49
|
227 push @Command_Lines, \%cl;
|
devi@49
|
228 }
|
devi@23
|
229 }
|
devi@23
|
230
|
devi@32
|
231 sub load_sessions_from_xml
|
devi@32
|
232 {
|
devi@49
|
233 my $datafile = $_[0];
|
devi@32
|
234
|
devi@49
|
235 open (CLASS, $datafile)
|
devi@49
|
236 or die "Can't open file of the class ",$datafile,"\n";
|
devi@49
|
237 local $/;
|
devi@49
|
238 my $data = <CLASS>;
|
devi@49
|
239 close(CLASS);
|
devi@32
|
240
|
devi@49
|
241 for my $session ($data =~ m@<session>(.*?)</session>@sg) {
|
devi@49
|
242 my %session;
|
devi@49
|
243 while ($session =~ m@<([^>]*?)>(.*?)</\1>@sg) {
|
devi@49
|
244 $session{$1} = $2;
|
devi@49
|
245 }
|
devi@49
|
246 $Sessions{$session{local_session_id}} = \%session;
|
devi@49
|
247 }
|
devi@32
|
248 }
|
devi@32
|
249
|
devi@32
|
250
|
devi@32
|
251
|
devi@31
|
252 sub sort_command_lines
|
devi@31
|
253 {
|
devi@49
|
254 # Sort Command_Lines
|
devi@49
|
255 # Write Command_Lines to Command_Lines_Index
|
devi@31
|
256
|
devi@49
|
257 my @index;
|
devi@49
|
258 for (my $i=0;$i<=$#Command_Lines;$i++) {
|
devi@49
|
259 $index[$i]=$i;
|
devi@49
|
260 }
|
devi@31
|
261
|
devi@49
|
262 @Command_Lines_Index = sort {
|
devi@49
|
263 $Command_Lines[$index[$a]]->{"time"} <=> $Command_Lines[$index[$b]]->{"time"}
|
devi@49
|
264 } @index;
|
devi@31
|
265
|
devi@31
|
266 }
|
devi@31
|
267
|
devi@31
|
268 sub process_command_lines
|
devi@31
|
269 {
|
devi@49
|
270 for my $i (@Command_Lines_Index) {
|
devi@31
|
271
|
devi@49
|
272 my $cl = \$Command_Lines[$i];
|
devi@49
|
273 #@{${$cl}->{"new_commands"}} =();
|
devi@49
|
274 #@{${$cl}->{"new_files"}} =();
|
devi@49
|
275 $$cl->{"class"} = "";
|
devi@31
|
276
|
devi@49
|
277 if ($$cl->{"err"}) {
|
devi@49
|
278 $$cl->{"class"}="wrong";
|
devi@49
|
279 $$cl->{"class"}="interrupted"
|
devi@49
|
280 if ($$cl->{"err"} eq 130);
|
devi@49
|
281 }
|
devi@49
|
282 if (!$$cl->{"euid"}) {
|
devi@49
|
283 $$cl->{"class"}.="_root";
|
devi@49
|
284 }
|
devi@49
|
285
|
devi@49
|
286 #tab# my @tab_words=split /\s+/, $$cl->{"output"};
|
devi@49
|
287 #tab# my $last_word= $$cl->{"cline"} =~ /(\S*)$/;
|
devi@49
|
288 #tab# $last_word =~ s@.*/@@;
|
devi@49
|
289 #tab# my $this_is_tab=1;
|
devi@31
|
290 #tab#
|
devi@49
|
291 #tab# if ($last_word && @tab_words >2) {
|
devi@49
|
292 #tab# for my $tab_words (@tab_words) {
|
devi@49
|
293 #tab# if ($tab_words !~ /^$last_word/) {
|
devi@49
|
294 #tab# $this_is_tab=0;
|
devi@49
|
295 #tab# last;
|
devi@49
|
296 #tab# }
|
devi@49
|
297 #tab# }
|
devi@49
|
298 #tab# }
|
devi@49
|
299 #tab# $$cl->{"class"}="tab" if $this_is_tab;
|
devi@49
|
300
|
devi@31
|
301
|
devi@49
|
302 # if ( !$$cl->{"err"}) {
|
devi@49
|
303 # # Command does not contain mistakes
|
devi@49
|
304 #
|
devi@49
|
305 # my %commands = extract_from_cline("commands", ${$cl}->{"cline"});
|
devi@49
|
306 # my %files = extract_from_cline("files", ${$cl}->{"cline"});
|
devi@31
|
307 #
|
devi@49
|
308 # # Searching for new commands only
|
devi@49
|
309 # for my $command (keys %commands) {
|
devi@49
|
310 # if (!defined $Commands_Stat{$command}) {
|
devi@49
|
311 # push @{$$cl->{new_commands}}, $command;
|
devi@49
|
312 # }
|
devi@49
|
313 # $Commands_Stat{$command}++;
|
devi@49
|
314 # }
|
devi@49
|
315 #
|
devi@49
|
316 # for my $file (keys %files) {
|
devi@49
|
317 # if (!defined $Files_Stat{$file}) {
|
devi@49
|
318 # push @{$$cl->{new_files}}, $file;
|
devi@49
|
319 # }
|
devi@49
|
320 # $Files_Stat{$file}++;
|
devi@49
|
321 # }
|
devi@49
|
322 # }
|
devi@31
|
323
|
devi@49
|
324 if ($$cl->{cline}=~ m@cat[^#]*#([\^=v])\s*(.*)@) {
|
devi@49
|
325 if ($1 eq "=") {
|
devi@49
|
326 $$cl->{"class"} = "note";
|
devi@49
|
327 $$cl->{"note"} = $$cl->{"output"};
|
devi@49
|
328 $$cl->{"note_title"} = $2;
|
devi@49
|
329 }
|
devi@49
|
330 else {
|
devi@49
|
331 my $j = $i;
|
devi@49
|
332 if ($1 eq "^") {
|
devi@49
|
333 $j--;
|
devi@49
|
334 $j-- while ($j >=0 && (!$Command_Lines[$j] || $Command_Lines[$j]->{tty} ne $$cl->{tty}));
|
devi@49
|
335 }
|
devi@49
|
336 elsif ($1 eq "v") {
|
devi@49
|
337 $j++;
|
devi@49
|
338 $j++ while ($j <= @Command_Lines && (!$Command_Lines[$j] || $Command_Lines[$j]->{tty} ne $$cl->{tty}));
|
devi@49
|
339 }
|
devi@49
|
340 $Command_Lines[$j]->{note_title}="$2";
|
devi@49
|
341 $Command_Lines[$j]->{note}=$$cl->{output};
|
devi@49
|
342 $$cl=0;
|
devi@49
|
343 }
|
devi@49
|
344 }
|
devi@49
|
345 elsif ($$cl->{cline}=~ /#([\^=v])(.*)/) {
|
devi@49
|
346 if ($1 eq "=") {
|
devi@49
|
347 $$cl->{"class"} = "note";
|
devi@49
|
348 $$cl->{"note"} = $2;
|
devi@49
|
349 }
|
devi@49
|
350 else {
|
devi@49
|
351 my $j=$i;
|
devi@49
|
352 if ($1 eq "^") {
|
devi@49
|
353 $j--;
|
devi@49
|
354 $j-- while ($j >=0 && (!$Command_Lines[$j] || $Command_Lines[$j]->{tty} ne $$cl->{tty}));
|
devi@49
|
355 }
|
devi@49
|
356 elsif ($1 eq "v") {
|
devi@49
|
357 $j++;
|
devi@49
|
358 $j++ while ($j <= @Command_Lines && $Command_Lines[$j]->{tty} ne $$cl->{tty} || !$Command_Lines[$j]);
|
devi@49
|
359 }
|
devi@49
|
360 $Command_Lines[$j]->{note}.="$2\n";
|
devi@49
|
361 $$cl=0;
|
devi@49
|
362 }
|
devi@49
|
363 }
|
devi@49
|
364 }
|
devi@31
|
365
|
devi@31
|
366 }
|
devi@31
|
367
|
devi@31
|
368
|
devi@23
|
369 =cut
|
devi@23
|
370 Процедура print_command_lines выводит HTML-представление
|
devi@23
|
371 разобранного lab-скрипта.
|
devi@23
|
372
|
devi@23
|
373 Разобранный lab-скрипт должен находиться в массиве @Command_Lines
|
devi@23
|
374 =cut
|
devi@23
|
375
|
devi@23
|
376 sub print_command_lines
|
devi@23
|
377 {
|
devi@49
|
378 my $output_filename=$_[0];
|
devi@23
|
379
|
devi@49
|
380 my $course_name = $Config{"course-name"};
|
devi@49
|
381 my $course_code = $Config{"course-code"};
|
devi@49
|
382 my $course_date = $Config{"course-date"};
|
devi@49
|
383 my $course_center = $Config{"course-center"};
|
devi@49
|
384 my $course_trainer = $Config{"course-trainer"};
|
devi@49
|
385 my $course_student = $Config{"course-student"};
|
devi@49
|
386
|
devi@23
|
387
|
devi@49
|
388 # Результат выполнения процедуры равен
|
devi@49
|
389 # join("", @Result{header,body,stat,help,about,footer})
|
devi@49
|
390 my %Result;
|
devi@49
|
391 my @toc; # Хранит оглавление
|
devi@49
|
392 my $note_number=0;
|
devi@23
|
393
|
devi@49
|
394 $Result{"body"} = "<table width='100%'>\n";
|
devi@49
|
395
|
devi@49
|
396 my $cl;
|
devi@49
|
397 my $last_tty="";
|
devi@49
|
398 my $last_day="";
|
devi@49
|
399 my $in_range=0;
|
devi@23
|
400
|
devi@49
|
401 my $current_command=0;
|
devi@32
|
402
|
devi@32
|
403 COMMAND_LINE:
|
devi@49
|
404 for my $k (@Command_Lines_Index) {
|
devi@31
|
405
|
devi@49
|
406 my $cl=$Command_Lines[$Command_Lines_Index[$current_command++]];
|
devi@49
|
407
|
devi@49
|
408 next unless $cl;
|
devi@23
|
409
|
devi@32
|
410
|
devi@49
|
411 if ($Config{filter}) {
|
devi@49
|
412 # Инициализация фильтра
|
devi@49
|
413 my %filter;
|
devi@49
|
414 for (split /&/,$Config{filter}) {
|
devi@49
|
415 my ($var, $val) = split /=/;
|
devi@49
|
416 $filter{$var} = $val || "";
|
devi@49
|
417 }
|
devi@32
|
418
|
devi@49
|
419 for my $filter_key (keys %filter) {
|
devi@52
|
420 next COMMAND_LINE if
|
devi@52
|
421 defined($cl->{local_session_id})
|
devi@52
|
422 && defined($Sessions{$cl->{local_session_id}}->{$filter_key})
|
devi@52
|
423 && $Sessions{$cl->{local_session_id}}->{$filter_key} ne $filter{$filter_key};
|
devi@52
|
424 #print $filter_key,"\n";
|
devi@49
|
425 }
|
devi@32
|
426
|
devi@49
|
427 #if ($filter{user}) {
|
devi@49
|
428 # next COMMAND_LINE unless $Sessions{$cl->{local_session_id}}->{user} eq $filter{user};
|
devi@49
|
429 #}
|
devi@35
|
430
|
devi@49
|
431 #for my $filter_field (keys %filter) {
|
devi@49
|
432 # next COMMAND_LINE unless $Sessions{$cl->{local_session_id}}->{$filter_field} eq $filter{$filter_field};
|
devi@49
|
433 #}
|
devi@49
|
434 }
|
devi@32
|
435
|
devi@49
|
436 if ($Config{"from"} && $cl->{"cline"} =~ /$Config{"signature"}\s*$Config{"from"}/) {
|
devi@49
|
437 $in_range=1;
|
devi@49
|
438 next;
|
devi@49
|
439 }
|
devi@49
|
440 if ($Config{"to"} && $cl->{"cline"} =~ /$Config{"signature"}\s*$Config{"to"}/) {
|
devi@49
|
441 $in_range=0;
|
devi@49
|
442 next;
|
devi@49
|
443 }
|
devi@49
|
444 next if ($Config{"from"} && $Config{"to"} && !$in_range)
|
devi@49
|
445 ||
|
devi@49
|
446 ($Config{"skip_empty"} =~ /^y/i && $cl->{"cline"} =~ /^\s*$/ )
|
devi@49
|
447 ||
|
devi@49
|
448 ($Config{"skip_wrong"} =~ /^y/i && $cl->{"err"} != 0)
|
devi@49
|
449 ||
|
devi@49
|
450 ($Config{"skip_interrupted"} =~ /^y/i && $cl->{"err"} == 130);
|
devi@49
|
451
|
devi@49
|
452 #my @new_commands=@{$cl->{"new_commands"}};
|
devi@49
|
453 #my @new_files=@{$cl->{"new_files"}};
|
devi@23
|
454
|
devi@49
|
455 if ($cl->{class} eq "note") {
|
devi@49
|
456 my $note = $cl->{note};
|
devi@49
|
457 $note = join ("\n", map ("<p>$_</p>", split (/-\n/, $note)));
|
devi@52
|
458 $note =~ s@(http:[a-zA-Z.0-9/?\_%-]*)@<a href='$1'>$1</a>@g;
|
devi@52
|
459 $note =~ s@(www\.[a-zA-Z.0-9/?\_%-]*)@<a href='$1'>$1</a>@g;
|
devi@49
|
460 $Result{"body"} .= "<tr><td colspan='6'>";
|
devi@49
|
461 $Result{"body"} .= "<h4 id='note$note_number'>".$cl->{note_title}."</h4>" if $cl->{note_title};
|
devi@49
|
462 $Result{"body"} .= "".$note."<p/><p/></td></td>";
|
devi@31
|
463
|
devi@49
|
464 if ($cl->{note_title}) {
|
devi@49
|
465 push @{$toc[@toc]},"<a href='#note$note_number'>".$cl->{note_title}."</a>";
|
devi@49
|
466 $note_number++;
|
devi@49
|
467 }
|
devi@49
|
468 next;
|
devi@49
|
469 }
|
devi@31
|
470
|
devi@49
|
471 my $cl_class="cline";
|
devi@49
|
472 my $out_class="output";
|
devi@49
|
473 if ($cl->{"class"}) {
|
devi@49
|
474 $cl_class = $cl->{"class"}."_".$cl_class;
|
devi@49
|
475 $out_class = $cl->{"class"}."_".$out_class;
|
devi@49
|
476 }
|
devi@23
|
477
|
devi@49
|
478 my @new_commands;
|
devi@49
|
479 my @new_files;
|
devi@49
|
480 @new_commands = split (/\s+/, $cl->{"new_commands"}) if defined $cl->{"new_commands"};
|
devi@49
|
481 @new_files = split (/\s+/, $cl->{"new_files"}) if defined $cl->{"new_files"};
|
devi@23
|
482
|
devi@49
|
483 my $output="";
|
devi@49
|
484 if ($Config{"head_lines"} || $Config{"tail_lines"}) {
|
devi@49
|
485 # Partialy output
|
devi@49
|
486 my @lines = split '\n', $cl->{"output"};
|
devi@49
|
487 # head
|
devi@49
|
488 my $mark=1;
|
devi@49
|
489 for (my $i=0; $i<= $#lines && $i < $Config{"head_lines"}; $i++) {
|
devi@49
|
490 $output .= $lines[$i]."\n";
|
devi@49
|
491 }
|
devi@49
|
492 # tail
|
devi@49
|
493 my $start=$#lines-$Config{"tail_lines"}+1;
|
devi@49
|
494 if ($start < 0) {
|
devi@49
|
495 $start=0;
|
devi@49
|
496 $mark=0;
|
devi@49
|
497 }
|
devi@49
|
498 if ($start < $Config{"head_lines"}) {
|
devi@49
|
499 $start=$Config{"head_lines"};
|
devi@49
|
500 $mark=0;
|
devi@49
|
501 }
|
devi@49
|
502 $output .= $Config{"skip_text"}."\n" if $mark;
|
devi@49
|
503 for ($i=$start; $i<= $#lines; $i++) {
|
devi@49
|
504 $output .= $lines[$i]."\n";
|
devi@49
|
505 }
|
devi@49
|
506 }
|
devi@49
|
507 else {
|
devi@49
|
508 # Full output
|
devi@49
|
509 $output .= $cl->{"output"};
|
devi@49
|
510 }
|
devi@49
|
511 #$output .= "^C\n" if ($cl->{"err"} eq "130");
|
devi@23
|
512
|
devi@49
|
513 #
|
devi@49
|
514 ##
|
devi@49
|
515 ## Начинается собственно вывод
|
devi@49
|
516 ##
|
devi@49
|
517 #
|
devi@23
|
518
|
devi@49
|
519 # <command>
|
devi@23
|
520
|
devi@49
|
521 my ($sec,$min,$hour,$day,$mon,$year,$wday,$yday,$isdst) = localtime($cl->{time});
|
devi@49
|
522 next if $Stat{LastCommand} == $cl->{time};
|
devi@49
|
523 $Stat{FirstCommand} = $cl->{time} unless $Stat{FirstCommand};
|
devi@49
|
524 $Stat{LastCommand} = 0 unless defined $Stat{LastCommand};
|
devi@49
|
525 $Stat{TotalTime} += $cl->{time} - $Stat{LastCommand}
|
devi@49
|
526 if $cl->{time} - $Stat{LastCommand} < $Config{stat_inactivity_interval};
|
devi@49
|
527 $Stat{LastCommand} = $cl->{time};
|
devi@49
|
528 $Stat{TotalCommands} = 0 unless $Stat{TotalCommands};
|
devi@49
|
529 $Stat{TotalCommands}++;
|
devi@31
|
530
|
devi@49
|
531 # Добавляем спереди 0 для удобочитаемости
|
devi@49
|
532 $min = "0".$min if $min =~ /^.$/;
|
devi@49
|
533 $hour = "0".$hour if $hour =~ /^.$/;
|
devi@49
|
534 $sec = "0".$sec if $sec =~ /^.$/;
|
devi@23
|
535
|
devi@49
|
536 $class=$cl->{"out_class"};
|
devi@49
|
537 $class =~ s/output$//;
|
devi@23
|
538
|
devi@49
|
539 $Stat{ErrorCommands}++
|
devi@49
|
540 if $class =~ /wrong/;
|
devi@49
|
541
|
devi@49
|
542 $Result{"body"} .= "<tr class='command'>\n";
|
devi@49
|
543
|
devi@49
|
544
|
devi@49
|
545 # DAY CHANGE
|
devi@49
|
546 if ( $last_day ne $day) {
|
devi@49
|
547 #$Result{"body"} .= "<td colspan='6'><p></p><h3>День ",$day,"</h4></td></tr><tr>";
|
devi@49
|
548 $Result{"body"} .= "<td colspan='6'><p></p><h3 id='day$day'>".$Day_Name[$wday]."</h4></td></tr><tr>";
|
devi@49
|
549 push @toc, "<a href='#day$day'>".$Day_Name[$wday]."</a>\n";
|
devi@49
|
550 $last_day=$day;
|
devi@49
|
551 }
|
devi@23
|
552
|
devi@49
|
553 # CONSOLE CHANGE
|
devi@49
|
554 if ( $last_tty ne $cl->{"tty"}) {
|
devi@49
|
555 my $host;
|
devi@49
|
556 #$host = $Sessions{$cl->{local_session_id}}->{user}."@".$Sessions{$cl->{local_session_id}}->{hostname};
|
devi@49
|
557 my $body = $cl->{"tty"};
|
devi@49
|
558 $body .= " \@$host" if $host;
|
devi@49
|
559 $Result{"body"} .= "<td colspan='6'><table><tr><td class='ttychange' width='140' align='center'>".$body."</td></tr></table></td></tr><tr>";
|
devi@49
|
560 $last_tty=$cl->{"tty"};
|
devi@49
|
561 }
|
devi@23
|
562
|
devi@49
|
563 # TIME
|
devi@49
|
564 if ($Config{"show_time"} =~ /^y/i) {
|
devi@49
|
565 $Result{"body"} .= "<td valign='top' class='time' width='$Config{time_width}'><pre>".
|
devi@49
|
566 $hour. ":". $min. ":". $sec.
|
devi@49
|
567 "</td>";
|
devi@49
|
568 } else {
|
devi@49
|
569 $Result{"body"} .= "<td width='0'/>"
|
devi@49
|
570 }
|
devi@23
|
571
|
devi@49
|
572 # COMMAND
|
devi@49
|
573 $Result{"body"} .= "<td class='script'>\n";
|
devi@49
|
574 $Result{"body"} .= "<pre class='${class}cline'>\n";
|
devi@49
|
575 my $cline = $cl->{"prompt"}.$cl->{"cline"};
|
devi@49
|
576 $cline =~ s/\n//;
|
devi@32
|
577
|
devi@49
|
578 #$cline .= "(".$Sessions{$cl->{local_session_id}}.")";
|
devi@49
|
579
|
devi@49
|
580 my $hint = make_comment($cl->{"cline"});
|
devi@55
|
581 $cline = "<span title='$hint' class='with_hint'>$cline</span>" if $hint;
|
devi@55
|
582 $cline = "<span class='without_hint'>$cline</span>" if !$hint;
|
devi@49
|
583 $Result{"body"} .= $cline;
|
devi@49
|
584 $Result{"body"} .= "</pre>\n";
|
devi@23
|
585
|
devi@49
|
586 my $last_command = $cl->{"last_command"};
|
devi@49
|
587 if (!(
|
devi@49
|
588 $Config{"suppress_editors"} =~ /^y/i && grep ($_ eq $last_command, @{$Config{"editors"}}) ||
|
devi@49
|
589 $Config{"suppress_pagers"} =~ /^y/i && grep ($_ eq $last_command, @{$Config{"pagers"}}) ||
|
devi@49
|
590 $Config{"suppress_terminal"}=~ /^y/i && grep ($_ eq $last_command, @{$Config{"terminal"}})
|
devi@49
|
591 )) {
|
devi@23
|
592
|
devi@49
|
593 $Result{"body"} .= "<pre class='".$cl->{out_class}."'>";
|
devi@49
|
594 $Result{"body"} .= $output;
|
devi@49
|
595 $Result{"body"} .= "</pre>\n";
|
devi@49
|
596 }
|
devi@23
|
597
|
devi@49
|
598 # DIFF
|
devi@49
|
599 if ( $Config{"show_diffs"} =~ /^y/i && $cl->{"diff"}) {
|
devi@49
|
600 $Result{"body"} .= "<table><tr><td width='5'/><td class='diff'><pre>";
|
devi@49
|
601 $Result{"body"} .= $cl->{"diff"};
|
devi@49
|
602 $Result{"body"} .= "</pre></td></tr></table>";
|
devi@49
|
603 }
|
devi@49
|
604
|
devi@49
|
605 #NOTES
|
devi@49
|
606 if ( $Config{"show_notes"} =~ /^y/i && $cl->{"note"}) {
|
devi@49
|
607 my $note=$cl->{"note"};
|
devi@49
|
608 $note =~ s/\n/<br\/>\n/msg;
|
devi@52
|
609 if (not $note =~ s@(http:[a-zA-Z.0-9/_?%-]*)@<a href='$1'>$1</a>@g) {
|
devi@52
|
610 $note =~ s@(www\.[a-zA-Z.0-9/_?%-]*)@<a href='$1'>$1</a>@g;
|
devi@52
|
611 };
|
devi@49
|
612 # Ширину пока не используем
|
devi@49
|
613 # $Result{"body"} .= "<table width='$Config{note_width}' class='note'>";
|
devi@49
|
614 $Result{"body"} .= "<table class='note'>";
|
devi@49
|
615 $Result{"body"} .= "<tr><td class='note_title'>".$cl->{note_title}."</td></tr>" if $cl->{note_title};
|
devi@49
|
616 $Result{"body"} .= "<tr><td width='100%' class='note_text'>".$note."</td></tr>";
|
devi@49
|
617 $Result{"body"} .= "</table>\n";
|
devi@49
|
618 }
|
devi@23
|
619
|
devi@49
|
620 # COMMENT
|
devi@49
|
621 if ( $Config{"show_comments"} =~ /^y/i) {
|
devi@49
|
622 my $comment = make_comment($cl->{"cline"});
|
devi@49
|
623 if ($comment) {
|
devi@49
|
624 $Result{"body"} .= "<table width='$Config{comment_width}'>".
|
devi@49
|
625 "<tr><td width='5'/><td>";
|
devi@49
|
626 $Result{"body"} .= "<table class='note' width='100%'>";
|
devi@49
|
627 $Result{"body"} .= $comment;
|
devi@49
|
628 $Result{"body"} .= "</table>\n";
|
devi@49
|
629 $Result{"body"} .= "</td></tr></table>";
|
devi@49
|
630 }
|
devi@49
|
631 }
|
devi@23
|
632
|
devi@49
|
633 # Вывод очередной команды окончен
|
devi@49
|
634 $Result{"body"} .= "</td>\n";
|
devi@49
|
635 $Result{"body"} .= "</tr>\n";
|
devi@49
|
636 }
|
devi@23
|
637
|
devi@49
|
638 $Result{"body"} .= "</table>\n";
|
devi@23
|
639
|
devi@49
|
640 #$Result{"stat"} = "<hr/>";
|
devi@31
|
641
|
devi@49
|
642 %StatNames = (
|
devi@49
|
643 FirstCommand => "Время первой команды журнала",
|
devi@49
|
644 LastCommand => "Время последней команды журнала",
|
devi@49
|
645 TotalCommands => "Количество командных строк в журнале",
|
devi@49
|
646 ErrorsPercentage => "Процент команд с ненулевым кодом завершения, %",
|
devi@49
|
647 TotalTime => "Суммарное время работы с терминалом <sup><font size='-2'>*</font></sup>, час",
|
devi@49
|
648 CommandsPerTime => "Количество командных строк в единицу времени, команда/мин",
|
devi@49
|
649 CommandsFrequency => "Частота использования команд",
|
devi@49
|
650 RareCommands => "Частота использования этих команд < 0.5%",
|
devi@49
|
651 );
|
devi@49
|
652 @StatOrder = (
|
devi@49
|
653 FirstCommand,
|
devi@49
|
654 LastCommand,
|
devi@49
|
655 TotalCommands,
|
devi@49
|
656 ErrorsPercentage,
|
devi@49
|
657 TotalTime,
|
devi@49
|
658 CommandsPerTime,
|
devi@49
|
659 CommandsFrequency,
|
devi@49
|
660 RareCommands,
|
devi@49
|
661 );
|
devi@31
|
662
|
devi@49
|
663 # Подготовка статистики к выводу
|
devi@49
|
664 # Некоторые значения пересчитываются!
|
devi@49
|
665 # Дальше их лучше уже не использовать!!!
|
devi@31
|
666
|
devi@49
|
667 my %CommandsFrequency = %CommandsFDistribution;
|
devi@37
|
668
|
devi@49
|
669 $Stat{TotalTime} ||= 0;
|
devi@49
|
670 my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($Stat{FirstCommand} || 0);
|
devi@49
|
671 $Stat{FirstCommand} = sprintf "%02i:%02i:%02i %04i-%2i-%2i", $hour, $min, $sec, $year+1900, $mon+1, $mday;
|
devi@49
|
672 ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($Stat{LastCommand} || 0);
|
devi@49
|
673 $Stat{LastCommand} = sprintf "%02i:%02i:%02i %04i-%2i-%2i", $hour, $min, $sec, $year+1900, $mon+1, $mday;
|
devi@49
|
674 $Stat{ErrorsPercentage} = sprintf "%5.2f", $Stat{ErrorCommands}*100/$Stat{TotalCommands}
|
devi@49
|
675 if $Stat{TotalCommands};
|
devi@49
|
676 $Stat{CommandsPerTime} = sprintf "%5.2f", $Stat{TotalCommands}*60/$Stat{TotalTime}
|
devi@49
|
677 if $Stat{TotalTime};
|
devi@49
|
678 $Stat{TotalTime} = sprintf "%5.2f", $Stat{TotalTime}/60/60;
|
devi@31
|
679
|
devi@49
|
680 my $total_commands=0;
|
devi@49
|
681 for $command (keys %CommandsFrequency){
|
devi@49
|
682 $total_commands += $CommandsFrequency{$command};
|
devi@49
|
683 }
|
devi@49
|
684 if ($total_commands) {
|
devi@49
|
685 for $command (reverse sort {$CommandsFrequency{$a} <=> $CommandsFrequency{$b}} keys %CommandsFrequency){
|
devi@49
|
686 my $command_html;
|
devi@49
|
687 my $percentage = sprintf "%5.2f",$CommandsFrequency{$command}*100/$total_commands;
|
devi@49
|
688 if ($percentage < 0.5) {
|
devi@49
|
689 my $hint = make_comment($command);
|
devi@49
|
690 $command_html = "$command";
|
devi@49
|
691 $command_html = "<span title='$hint' class='hint'>$command_html</span>" if $hint;
|
devi@49
|
692 my $command_html = "<tt>$command_html</tt>";
|
devi@49
|
693 $Stat{RareCommands} .= $command_html."<sub><font size='-2'>".$CommandsFrequency{$command}."</font></sub> , ";
|
devi@49
|
694 }
|
devi@49
|
695 else {
|
devi@49
|
696 my $hint = make_comment($command);
|
devi@49
|
697 $command_html = "$command";
|
devi@49
|
698 $command_html = "<span title='$hint' class='hint'>$command_html</span>" if $hint;
|
devi@49
|
699 my $command_html = "<tt>$command_html</tt>";
|
devi@49
|
700 $percentage = sprintf "%5.2f",$percentage;
|
devi@49
|
701 $Stat{CommandsFrequency} .= "<tr><td>".$command_html."</td><td>".$CommandsFrequency{$command}."</td>".
|
devi@49
|
702 "<td>|".("="x int($CommandsFrequency{$command}*100/$total_commands))."| $percentage%</td></tr>";
|
devi@49
|
703 }
|
devi@49
|
704 }
|
devi@49
|
705 $Stat{CommandsFrequency} = "<table>".$Stat{CommandsFrequency}."</table>";
|
devi@49
|
706 $Stat{RareCommands} =~ s/, $// if $Stat{RareCommands};
|
devi@49
|
707 }
|
devi@31
|
708
|
devi@49
|
709 $Result{"stat"} .= "<h2 id='stat'>Статистика</h2>";
|
devi@49
|
710 $Result{"stat"} .= "<table>";
|
devi@49
|
711 for my $stat (@StatOrder) {
|
devi@49
|
712 $Result{"stat"} .= "<tr valign='top'><td width='300'>".$StatNames{"$stat"}."</td><td>".$Stat{"$stat"}."</td></tr>"
|
devi@49
|
713 if $Stat{"$stat"};
|
devi@49
|
714 }
|
devi@49
|
715
|
devi@49
|
716 $Result{"stat"} .= "</table>";
|
devi@49
|
717 $Result{"stat"} .= "<font size='-2'>____<br/>*) Интервалы неактивности длительностью ".($Config{stat_inactivity_interval}/60)." минут и более не учитываются</font></br>";
|
devi@31
|
718
|
devi@49
|
719 #$Result{"help"} .= "<hr/>";
|
devi@49
|
720 $Result{"help"} .= "<h2 id='help'>Справка</h2>";
|
devi@49
|
721 $Result{"help"} .= "$Html_Help<br/>";
|
devi@49
|
722 #$Result{"about"} .= "<hr/>";
|
devi@49
|
723 $Result{"about"} .= "<h2 id='about'>О программе</h2>";
|
devi@49
|
724 $Result{"about"} .= "$Html_About";
|
devi@49
|
725 $Result{"footer"} .= "</body>\n";
|
devi@49
|
726 $Result{"footer"} .= "</html>\n";
|
devi@23
|
727
|
devi@49
|
728 $Result{"title"} = "Журнал лабораторных работ";
|
devi@49
|
729 $Result{"title"}.= " -- ".$course_student if $course_student;
|
devi@49
|
730 if ($course_date) {
|
devi@49
|
731 $Result{"title"}.= " -- ".$course_date;
|
devi@49
|
732 $Result{"title"}.= "/".$course_code if $course_code;
|
devi@49
|
733 }
|
devi@49
|
734 else {
|
devi@49
|
735 $Result{"title"}.= " -- ".$course_code if $course_code;
|
devi@49
|
736 }
|
devi@31
|
737
|
devi@49
|
738 # Заголовок генерируется позже всего
|
devi@49
|
739 # Тогда, когда известно уже, что должно быть написано в
|
devi@49
|
740 # оглавлении
|
devi@49
|
741 $Result{"header"} = <<HEADER;
|
devi@49
|
742 <html>
|
devi@49
|
743 <head>
|
devi@49
|
744 <meta content='text/html; charset=utf-8' http-equiv='Content-Type' />
|
devi@49
|
745 <link rel='stylesheet' href='$Config{frontend_css}' type='text/css'/>
|
devi@49
|
746 <title>$Result{title}</title>
|
devi@49
|
747 </head>
|
devi@49
|
748 <body>
|
devi@49
|
749 <script>
|
devi@49
|
750 $Html_JavaScript
|
devi@49
|
751 </script>
|
devi@49
|
752 <h1>Журнал лабораторных работ</h1>
|
devi@23
|
753
|
devi@31
|
754 HEADER
|
devi@49
|
755 $Result{"header"} .= "<p>" if $course_student || $course_trainer || $course_name || $course_code || $course_date || $course_center;
|
devi@49
|
756 $Result{"header"} .= "Выполнил $course_student<br/>" if $course_student;
|
devi@49
|
757 $Result{"header"} .= "Проверил $course_trainer <br/>" if $course_trainer;
|
devi@49
|
758 $Result{"header"} .= "Курс " if $course_name || $course_code || $course_date;
|
devi@49
|
759 $Result{"header"} .= "$course_name " if $course_name;
|
devi@49
|
760 $Result{"header"} .= "($course_code)" if $course_code;
|
devi@49
|
761 $Result{"header"} .= ", $course_date<br/>" if $course_date;
|
devi@49
|
762 $Result{"header"} .= "Учебный центр $course_center <br/>" if $course_center;
|
devi@49
|
763 $Result{"header"} .= "</p>" if $course_student || $course_trainer || $course_name || $course_code || $course_date || $course_center;
|
devi@23
|
764
|
devi@49
|
765 my $toc = collapse_list (\@toc);
|
devi@49
|
766 $Result{"header"} .= <<HEADER;
|
devi@49
|
767 <table border=0 id='toc' class='toc'>
|
devi@49
|
768 <tr>
|
devi@49
|
769 <td>
|
devi@49
|
770 <div class='toc_title'>Содержание</div>
|
devi@49
|
771 <ul>
|
devi@49
|
772 <li><a href='#log'>Журнал</a></li>
|
devi@49
|
773 <ul>$toc</ul>
|
devi@49
|
774 <li><a href='#stat'>Статистика</a></li>
|
devi@49
|
775 <li><a href='#help'>Справка</a></li>
|
devi@49
|
776 <li><a href='#about'>О программе</a></li>
|
devi@49
|
777 </ul>
|
devi@49
|
778 </td>
|
devi@49
|
779 </tr>
|
devi@49
|
780 </table>
|
devi@23
|
781
|
devi@49
|
782 <h2 id="log">Журнал</h2>
|
devi@23
|
783 HEADER
|
devi@49
|
784 $Result{"header"} .= "<table id='visibility_form' class='visibility_form'><tr><td><form>\n";
|
devi@49
|
785 for my $element (keys %Elements_Visibility)
|
devi@49
|
786 {
|
devi@49
|
787 my @e = split /\s+/, $element;
|
devi@49
|
788 my $showhide = join "", map { "ShowHide('$_');" } @e ;
|
devi@49
|
789 $Result{"header"} .= "<input type='checkbox' name='$e[0]' onclick=\"$showhide\" checked>".
|
devi@49
|
790 $Elements_Visibility{$element}.
|
devi@49
|
791 "</input><br>\n";
|
devi@49
|
792 }
|
devi@23
|
793
|
devi@49
|
794 $Result{"header"} .= "</form></td></tr></table>\n";
|
devi@23
|
795
|
devi@49
|
796 if ($output_filename eq "-") {
|
devi@49
|
797 print $Result{"header"}, $Result{"body"}, $Result{"stat"}, $Result{"help"}, $Result{"about"}, $Result{"footer"};
|
devi@49
|
798 }
|
devi@49
|
799 else {
|
devi@49
|
800 open(OUT, ">", $output_filename)
|
devi@49
|
801 or die "Can't open $output_filename for writing\n";
|
devi@49
|
802 print OUT $Result{"header"}, $Result{"body"}, $Result{"stat"}, $Result{"help"}, $Result{"about"}, $Result{"footer"};
|
devi@49
|
803 close(OUT);
|
devi@49
|
804 }
|
devi@23
|
805 }
|
devi@23
|
806
|
devi@23
|
807
|
devi@23
|
808
|
devi@31
|
809 sub collapse_list($)
|
devi@31
|
810 {
|
devi@49
|
811 my $res = "";
|
devi@49
|
812 for my $elem (@{$_[0]}) {
|
devi@49
|
813 if (ref $elem eq "ARRAY") {
|
devi@49
|
814 $res .= "<ul>".collapse_list($elem)."</ul>";
|
devi@49
|
815 }
|
devi@49
|
816 else
|
devi@49
|
817 {
|
devi@49
|
818 $res .= "<li>".$elem."</li>";
|
devi@49
|
819 }
|
devi@49
|
820 }
|
devi@49
|
821 return $res;
|
devi@31
|
822 }
|
devi@31
|
823
|
devi@23
|
824
|
devi@23
|
825
|
devi@23
|
826
|
devi@23
|
827 sub init_variables
|
devi@23
|
828 {
|
devi@23
|
829 $Html_Help = <<HELP;
|
devi@49
|
830 Для того чтобы использовать LiLaLo, не нужно знать ничего особенного:
|
devi@49
|
831 всё происходит само собой.
|
devi@49
|
832 Однако, чтобы ведение и последующее использование журналов
|
devi@49
|
833 было как можно более эффективным, желательно иметь в виду следующее:
|
devi@49
|
834 <ul>
|
devi@49
|
835 <li><p>
|
devi@49
|
836 В журнал автоматически попадают все команды, данные в любом терминале системы.
|
devi@49
|
837 </p></li>
|
devi@49
|
838 <li><p>
|
devi@49
|
839 Для того чтобы убедиться, что журнал на текущем терминале ведётся,
|
devi@49
|
840 и команды записываются, дайте команду w.
|
devi@49
|
841 В поле WHAT, соответствующем текущему терминалу,
|
devi@49
|
842 должна быть указана программа script.
|
devi@49
|
843 </p></li>
|
devi@49
|
844 <li><p>
|
devi@49
|
845 Если код завершения команды равен нулю,
|
devi@49
|
846 команда была выполнена без ошибок.
|
devi@49
|
847 Команды, код завершения которых отличен от нуля, выделяются цветом.
|
devi@31
|
848 <table>
|
devi@31
|
849 <tr class='command'>
|
devi@31
|
850 <td class='script'>
|
devi@31
|
851 <pre class='wrong_cline'>
|
devi@31
|
852 \$ l s-l</pre>
|
devi@31
|
853 <pre class='wrong_output'>bash: l: command not found
|
devi@31
|
854 </pre>
|
devi@31
|
855 </td>
|
devi@31
|
856 </tr>
|
devi@31
|
857 </table>
|
devi@31
|
858 <br/>
|
devi@49
|
859 </p></li>
|
devi@49
|
860 <li><p>
|
devi@49
|
861 Команды, ход выполнения которых был прерван пользователем, выделяются цветом.
|
devi@31
|
862 <table>
|
devi@31
|
863 <tr class='command'>
|
devi@31
|
864 <td class='script'>
|
devi@31
|
865 <pre class='interrupted_cline'>
|
devi@31
|
866 \$ find / -name abc</pre>
|
devi@31
|
867 <pre class='interrupted_output'>find: /home/devi-orig/.gnome2: Keine Berechtigung
|
devi@31
|
868 find: /home/devi-orig/.gnome2_private: Keine Berechtigung
|
devi@31
|
869 find: /home/devi-orig/.nautilus/metafiles: Keine Berechtigung
|
devi@31
|
870 find: /home/devi-orig/.metacity: Keine Berechtigung
|
devi@31
|
871 find: /home/devi-orig/.inkscape: Keine Berechtigung
|
devi@31
|
872 ^C
|
devi@31
|
873 </pre>
|
devi@31
|
874 </td>
|
devi@31
|
875 </tr>
|
devi@31
|
876 </table>
|
devi@31
|
877 <br/>
|
devi@49
|
878 </p></li>
|
devi@49
|
879 <li><p>
|
devi@49
|
880 Команды, выполненные с привилегиями суперпользователя,
|
devi@49
|
881 выделяются слева красной чертой.
|
devi@31
|
882 <table>
|
devi@31
|
883 <tr class='command'>
|
devi@31
|
884 <td class='script'>
|
devi@31
|
885 <pre class='_root_cline'>
|
devi@31
|
886 # id</pre>
|
devi@31
|
887 <pre class='_root_output'>
|
devi@31
|
888 uid=0(root) gid=0(root) Gruppen=0(root)
|
devi@31
|
889 </pre>
|
devi@31
|
890 </td>
|
devi@31
|
891 </tr>
|
devi@31
|
892 </table>
|
devi@49
|
893 <br/>
|
devi@49
|
894 </p></li>
|
devi@49
|
895 <li><p>
|
devi@49
|
896 Изменения, внесённые в текстовый файл с помощью редактора,
|
devi@49
|
897 запоминаются и показываются в журнале в формате ed.
|
devi@49
|
898 Строки, начинающиеся символом "<", удалены, а строки,
|
devi@49
|
899 начинающиеся символом ">" -- добавлены.
|
devi@31
|
900 <table>
|
devi@31
|
901 <tr class='command'>
|
devi@31
|
902 <td class='script'>
|
devi@31
|
903 <pre class='cline'>
|
devi@31
|
904 \$ vi ~/.bashrc</pre>
|
devi@31
|
905 <table><tr><td width='5'/><td class='diff'><pre>2a3,5
|
devi@49
|
906 > if [ -f /usr/local/etc/bash_completion ]; then
|
devi@31
|
907 > . /usr/local/etc/bash_completion
|
devi@49
|
908 > fi
|
devi@31
|
909 </pre></td></tr></table></td>
|
devi@31
|
910 </tr>
|
devi@31
|
911 </table>
|
devi@49
|
912 <br/>
|
devi@49
|
913 </p></li>
|
devi@49
|
914 <li><p>
|
devi@49
|
915 Для того чтобы изменить файл в соответствии с показанными в диффшоте
|
devi@49
|
916 изменениями, можно воспользоваться командой patch.
|
devi@49
|
917 Нужно скопировать изменения, запустить программу patch, указав в
|
devi@49
|
918 качестве её аргумента файл, к которому применяются изменения,
|
devi@49
|
919 и всавить скопированный текст:
|
devi@48
|
920 <table>
|
devi@48
|
921 <tr class='command'>
|
devi@48
|
922 <td class='script'>
|
devi@48
|
923 <pre class='cline'>
|
devi@48
|
924 \$ patch ~/.bashrc</pre>
|
devi@48
|
925 </td>
|
devi@48
|
926 </tr>
|
devi@48
|
927 </table>
|
devi@49
|
928 В данном случае изменения применяются к файлу ~/.bashrc
|
devi@49
|
929 </p></li>
|
devi@49
|
930 <li><p>
|
devi@49
|
931 Для того чтобы получить краткую справочную информацию о команде,
|
devi@49
|
932 нужно подвести к ней мышь. Во всплывающей подсказке появится краткое
|
devi@49
|
933 описание команды.
|
devi@49
|
934 </p></li>
|
devi@49
|
935 <li><p>
|
devi@49
|
936 Время ввода команды, показанное в журнале, соответствует времени
|
devi@49
|
937 <i>начала ввода командной строки</i>, которое равно тому моменту,
|
devi@49
|
938 когда на терминале появилось приглашение интерпретатора
|
devi@49
|
939 </p></li>
|
devi@49
|
940 <li><p>
|
devi@49
|
941 Имя терминала, на котором была введена команда, показано в специальном блоке.
|
devi@49
|
942 Этот блок показывается только в том случае, если терминал
|
devi@49
|
943 текущей команды отличается от терминала предыдущей.
|
devi@49
|
944 </p></li>
|
devi@49
|
945 <li><p>
|
devi@49
|
946 Вывод не интересующих вас в настоящий момент элементов журнала,
|
devi@49
|
947 таких как время, имя терминала и других, можно отключить.
|
devi@49
|
948 Для этого нужно воспользоваться <a href='#visibility_form'>формой управления журналом</a>
|
devi@49
|
949 вверху страницы.
|
devi@49
|
950 </p></li>
|
devi@49
|
951 <li><p>
|
devi@49
|
952 Небольшие комментарии к командам можно вставлять прямо из командной строки.
|
devi@49
|
953 Комментарий вводится прямо в командную строку, после символов #^ или #v.
|
devi@49
|
954 Символы ^ и v показывают направление выбора команды, к которой относится комментарий:
|
devi@49
|
955 ^ - к предыдущей, v - к следующей.
|
devi@49
|
956 Например, если в командной строке было введено:
|
devi@31
|
957 <pre class='cline'>
|
devi@31
|
958 \$ whoami
|
devi@31
|
959 </pre>
|
devi@31
|
960 <pre class='output'>
|
devi@31
|
961 user
|
devi@31
|
962 </pre>
|
devi@31
|
963 <pre class='cline'>
|
devi@31
|
964 \$ #^ Интересно, кто я?
|
devi@31
|
965 </pre>
|
devi@49
|
966 в журнале это будет выглядеть так:
|
devi@49
|
967
|
devi@31
|
968 <pre class='cline'>
|
devi@31
|
969 \$ whoami
|
devi@31
|
970 </pre>
|
devi@31
|
971 <pre class='output'>
|
devi@31
|
972 user
|
devi@31
|
973 </pre>
|
devi@31
|
974 <table class='note'><tr><td width='100%' class='note_text'>
|
devi@31
|
975 <tr> <td> Интересно, кто я?<br/> </td></tr></table>
|
devi@49
|
976 </p></li>
|
devi@49
|
977 <li><p>
|
devi@49
|
978 Если комментарий содержит несколько строк,
|
devi@49
|
979 его можно вставить в журнал следующим образом:
|
devi@31
|
980 <pre class='cline'>
|
devi@31
|
981 \$ whoami
|
devi@31
|
982 </pre>
|
devi@31
|
983 <pre class='output'>
|
devi@31
|
984 user
|
devi@31
|
985 </pre>
|
devi@31
|
986 <pre class='cline'>
|
devi@31
|
987 \$ cat > /dev/null #^ Интересно, кто я?
|
devi@31
|
988 </pre>
|
devi@31
|
989 <pre class='output'>
|
devi@31
|
990 Программа whoami выводит имя пользователя, под которым
|
devi@31
|
991 мы зарегистрировались в системе.
|
devi@31
|
992 -
|
devi@31
|
993 Она не может ответить на вопрос о нашем назначении
|
devi@31
|
994 в этом мире.
|
devi@31
|
995 </pre>
|
devi@49
|
996 В журнале это будет выглядеть так:
|
devi@31
|
997 <table>
|
devi@31
|
998 <tr class='command'>
|
devi@31
|
999 <td class='script'>
|
devi@31
|
1000 <pre class='cline'>
|
devi@31
|
1001 \$ whoami</pre>
|
devi@31
|
1002 <pre class='output'>user
|
devi@31
|
1003 </pre>
|
devi@31
|
1004 <table class='note'><tr><td class='note_title'>Интересно, кто я?</td></tr><tr><td width='100%' class='note_text'>
|
devi@31
|
1005 Программа whoami выводит имя пользователя, под которым<br/>
|
devi@31
|
1006 мы зарегистрировались в системе.<br/>
|
devi@31
|
1007 <br/>
|
devi@31
|
1008 Она не может ответить на вопрос о нашем назначении<br/>
|
devi@31
|
1009 в этом мире.<br/>
|
devi@31
|
1010 </td></tr></table>
|
devi@31
|
1011 </td>
|
devi@31
|
1012 </tr>
|
devi@31
|
1013 </table>
|
devi@49
|
1014 Для разделения нескольких абзацев между собой
|
devi@49
|
1015 используйте символ "-", один в строке.
|
devi@49
|
1016 <br/>
|
devi@31
|
1017 </p></li>
|
devi@49
|
1018 <li><p>
|
devi@49
|
1019 Комментарии, не относящиеся непосредственно ни к какой из команд,
|
devi@49
|
1020 добавляются точно таким же способом, только вместо симолов #^ или #v
|
devi@49
|
1021 нужно использовать символы #=
|
devi@49
|
1022 </p></li>
|
devi@31
|
1023 </ul>
|
devi@23
|
1024 HELP
|
devi@23
|
1025
|
devi@23
|
1026 $Html_About = <<ABOUT;
|
devi@49
|
1027 <p>
|
devi@49
|
1028 LiLaLo (L3) расшифровывается как Live Lab Log.<br/>
|
devi@49
|
1029 Программа разработана для повышения эффективности обучения Unix/Linux-системам.<br/>
|
devi@49
|
1030 (c) Игорь Чубин, 2004-2005<br/>
|
devi@49
|
1031 </p>
|
devi@23
|
1032 ABOUT
|
devi@23
|
1033 $Html_About.='$Id$ </p>';
|
devi@23
|
1034
|
devi@23
|
1035 $Html_JavaScript = <<JS;
|
devi@49
|
1036 function getElementsByClassName(Class_Name)
|
devi@49
|
1037 {
|
devi@49
|
1038 var Result=new Array();
|
devi@49
|
1039 var All_Elements=document.all || document.getElementsByTagName('*');
|
devi@49
|
1040 for (i=0; i<All_Elements.length; i++)
|
devi@49
|
1041 if (All_Elements[i].className==Class_Name)
|
devi@49
|
1042 Result.push(All_Elements[i]);
|
devi@49
|
1043 return Result;
|
devi@49
|
1044 }
|
devi@49
|
1045 function ShowHide (name)
|
devi@49
|
1046 {
|
devi@49
|
1047 elements=getElementsByClassName(name);
|
devi@49
|
1048 for(i=0; i<elements.length; i++)
|
devi@49
|
1049 if (elements[i].style.display == "none")
|
devi@49
|
1050 elements[i].style.display = "";
|
devi@49
|
1051 else
|
devi@49
|
1052 elements[i].style.display = "none";
|
devi@49
|
1053 //if (elements[i].style.visibility == "hidden")
|
devi@49
|
1054 // elements[i].style.visibility = "visible";
|
devi@49
|
1055 //else
|
devi@49
|
1056 // elements[i].style.visibility = "hidden";
|
devi@49
|
1057 }
|
devi@49
|
1058 function filter_by_output(text)
|
devi@49
|
1059 {
|
devi@49
|
1060
|
devi@49
|
1061 var jjj=0;
|
devi@49
|
1062
|
devi@49
|
1063 elements=getElementsByClassName('command');
|
devi@49
|
1064 for(i=0; i<elements.length; i++) {
|
devi@49
|
1065 subelems = elements[i].getElementsByTagName('pre');
|
devi@49
|
1066 for(j=0; j<subelems.length; j++) {
|
devi@49
|
1067 if (subelems[j].className = 'output') {
|
devi@49
|
1068 var str = new String(subelems[j].nodeValue);
|
devi@49
|
1069 if (jjj != 1) {
|
devi@49
|
1070 alert(str);
|
devi@49
|
1071 jjj=1;
|
devi@49
|
1072 }
|
devi@49
|
1073 if (str.indexOf(text) >0)
|
devi@49
|
1074 subelems[j].style.display = "none";
|
devi@49
|
1075 else
|
devi@49
|
1076 subelems[j].style.display = "";
|
devi@23
|
1077
|
devi@49
|
1078 }
|
devi@49
|
1079
|
devi@49
|
1080 }
|
devi@49
|
1081 }
|
devi@23
|
1082
|
devi@49
|
1083 }
|
devi@23
|
1084 JS
|
devi@23
|
1085
|
devi@23
|
1086 %Search_Machines = (
|
devi@49
|
1087 "google" => { "query" => "http://www.google.com/search?q=" ,
|
devi@49
|
1088 "icon" => "$Config{frontend_google_ico}" },
|
devi@49
|
1089 "freebsd" => { "query" => "http://www.freebsd.org/cgi/man.cgi?query=",
|
devi@49
|
1090 "icon" => "$Config{frontend_freebsd_ico}" },
|
devi@49
|
1091 "linux" => { "query" => "http://man.he.net/?topic=",
|
devi@49
|
1092 "icon" => "$Config{frontend_linux_ico}"},
|
devi@49
|
1093 "opennet" => { "query" => "http://www.opennet.ru/search.shtml?words=",
|
devi@49
|
1094 "icon" => "$Config{frontend_opennet_ico}"},
|
devi@49
|
1095 "local" => { "query" => "http://www.freebsd.org/cgi/man.cgi?query=",
|
devi@49
|
1096 "icon" => "$Config{frontend_local_ico}" },
|
devi@23
|
1097
|
devi@49
|
1098 );
|
devi@23
|
1099
|
devi@23
|
1100 %Elements_Visibility = (
|
devi@49
|
1101 "note" => "замечания",
|
devi@49
|
1102 "diff" => "редактор",
|
devi@49
|
1103 "time" => "время",
|
devi@49
|
1104 "ttychange" => "терминал",
|
devi@49
|
1105 "wrong_output wrong_cline wrong_root_output wrong_root_cline"
|
devi@49
|
1106 => "команды с ошибками",
|
devi@49
|
1107 "interrupted_output interrupted_cline interrupted_root_output interrupted_root_cline"
|
devi@49
|
1108 => "прерванные команды",
|
devi@49
|
1109 "tab_completion_output tab_completion_cline"
|
devi@49
|
1110 => "продолжение с помощью tab"
|
devi@23
|
1111 );
|
devi@23
|
1112
|
devi@23
|
1113 @Day_Name = qw/ Воскресенье Понедельник Вторник Среда Четверг Пятница Суббота /;
|
devi@23
|
1114 @Month_Name = qw/ Январь Февраль Март Апрель Май Июнь Июль Август Сентябрь Октябрь Ноябрь Декабрь /;
|
devi@23
|
1115 @Of_Month_Name = qw/ Января Февраля Марта Апреля Мая Июня Июля Августа Сентября Октября Ноября Декабря /;
|
devi@23
|
1116 }
|
devi@23
|
1117
|