From 84adefa331c4159d432d22840663c38f155cd4c1 Mon Sep 17 00:00:00 2001 From: Erlang/OTP Date: Fri, 20 Nov 2009 14:54:40 +0000 Subject: The R13B03 release. --- lib/stdlib/doc/src/shell.xml | 810 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 810 insertions(+) create mode 100644 lib/stdlib/doc/src/shell.xml (limited to 'lib/stdlib/doc/src/shell.xml') diff --git a/lib/stdlib/doc/src/shell.xml b/lib/stdlib/doc/src/shell.xml new file mode 100644 index 0000000000..24b845fee9 --- /dev/null +++ b/lib/stdlib/doc/src/shell.xml @@ -0,0 +1,810 @@ + + + + +
+ + 19962009 + Ericsson AB. All Rights Reserved. + + + The contents of this file are subject to the Erlang Public License, + Version 1.1, (the "License"); you may not use this file except in + compliance with the License. You should have received a copy of the + Erlang Public License along with this software. If not, it can be + retrieved online at http://www.erlang.org/. + + Software distributed under the License is distributed on an "AS IS" + basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + the License for the specific language governing rights and limitations + under the License. + + + + shell + Bjorn Gustavsson + Bjarne Dacker + 1 + Bjarne Däcker + + 97-01-24 + A + shell.sgml +
+ shell + The Erlang Shell + +

The module shell implements an Erlang shell. +

+

The shell is a user interface program + for entering expression sequences. The expressions are + evaluated and a value is returned. + A history mechanism saves previous commands and their + values, which can then be incorporated in later commands. + How many commands and results to save can be determined by the user, + either interactively, by calling shell:history/1 and + shell:results/1, or by setting the application configuration + parameters shell_history_length and + shell_saved_results for the application STDLIB. +

+

The shell uses a helper process for evaluating commands in + order to protect the history mechanism from exceptions. By + default the evaluator process is killed when an exception + occurs, but by calling shell:catch_exception/1 or by + setting the application configuration parameter + shell_catch_exception for the application STDLIB + this behavior can be changed. See also the example below. +

+

Variable bindings, and local process dictionary changes + which are generated in user expressions are preserved, and the variables + can be used in later commands to access their values. The + bindings can also be forgotten so the variables can be re-used. +

+

The special shell commands all have the syntax of (local) + function calls. They are evaluated as + normal function calls and many commands can be used in one + expression sequence. +

+

If a command (local function call) is not recognized by the + shell, an attempt is first made to find the function in the + module user_default, where customized local commands + can be placed. If found, then the function is evaluated. + Otherwise, an attempt is made to evaluate the function in the + module shell_default. The module + user_default must be explicitly loaded. +

+

The shell also permits the user to start multiple concurrent + jobs. A job can be regarded as a set of processes which can + communicate with the shell. +

+

There is some support for reading and printing records in + the shell. During compilation record expressions are translated + to tuple expressions. In runtime it is not known whether a tuple + actually represents a record. Nor are the record definitions + used by compiler available at runtime. So in order to read the + record syntax and print tuples as records when possible, record + definitions have to be maintained by the shell itself. The shell + commands for reading, defining, forgetting, listing, and + printing records are described below. Note that each job has its + own set of record definitions. To facilitate matters record + definitions in the modules shell_default and + user_default (if loaded) are read each time a new job is + started. For instance, adding the line

+ + -include_lib("kernel/include/file.hrl"). +

to user_default makes the definition of file_info + readily available in the shell. +

+

The shell runs in two modes:

+ + Normal (possibly restricted) mode, in which + commands can be edited and expressions evaluated. + + Job Control Mode JCL, in which jobs can be + started, killed, detached and connected. + + +

Only the currently connected job can 'talk' to the shell.

+
+ +
+ Shell Commands + + b() + +

Prints the current variable bindings.

+
+ f() + +

Removes all variable bindings. +

+
+ f(X) + +

Removes the binding of variable X. +

+
+ h() + +

Prints the history list. +

+
+ history(N) + +

Sets the number of previous commands to keep in the + history list to N. The previous number is returned. + The default number is 20. +

+
+ results(N) + +

Sets the number of results from previous commands to keep in + the history list to N. The previous number is returned. + The default number is 20. +

+
+ e(N) + +

Repeats the command N, if N is positive. If + it is negative, the Nth previous command is repeated + (i.e., e(-1) repeats the previous command). +

+
+ v(N) + +

Uses the return value of the command N in the + current command, if N is positive. If it is negative, + the return value of the Nth previous command is used + (i.e., v(-1) uses the value of the previous command). +

+
+ help() + +

Evaluates shell_default:help(). +

+
+ c(File) + +

Evaluates shell_default:c(File). This compiles + and loads code in File and purges old versions of + code, if necessary. Assumes that the file and module names + are the same. +

+
+ catch_exception(Bool) + +

Sets the exception handling of the evaluator process. The + previous exception handling is returned. The default + (false) is to kill the evaluator process when an + exception occurs, which causes the shell to create a new + evaluator process. When the exception handling is set to + true the evaluator process lives on which means that + for instance ports and ETS tables as well as processes + linked to the evaluator process survive the exception. +

+
+ rd(RecordName, RecordDefinition) + +

Defines a record in the shell. RecordName is + an atom and RecordDefinition lists the field names + and the default values. Usually record definitions are made + known to the shell by use of the rr commands + described below, but sometimes it is handy to define records + on the fly. +

+
+ rf() + +

Removes all record definitions, then reads record + definitions from the modules shell_default and + user_default (if loaded). Returns the names of the + records defined. +

+
+ rf(RecordNames) + +

Removes selected record definitions. + RecordNames is a record name or a list of record names. + Use '_' to remove all record definitions. +

+
+ rl() + +

Prints all record definitions. +

+
+ rl(RecordNames) + +

Prints selected record definitions. + RecordNames is a record name or a list of record names. +

+
+ rp(Term) + +

Prints a term using the record definitions known to the + shell. All of Term is printed; the depth is not + limited as is the case when a return value is printed. +

+
+ rr(Module) + +

Reads record definitions from a module's BEAM file. If + there are no record definitions in the BEAM file, the + source file is located and read instead. Returns the names + of the record definitions read. Module is an atom. +

+
+ rr(Wildcard) + +

Reads record definitions from files. Existing + definitions of any of the record names read are replaced. + Wildcard is a wildcard string as defined in + filelib(3) but not an atom. +

+
+ rr(WildcardOrModule, RecordNames) + +

Reads record definitions from files but + discards record names not mentioned in RecordNames (a + record name or a list of record names). +

+
+ rr(WildcardOrModule, RecordNames, Options) + +

Reads record definitions from files. The compiler + options {i, Dir}, {d, Macro}, and + {d, Macro, Value} are recognized and used + for setting up the include path and macro definitions. Use + '_' as value of RecordNames to read all record + definitions. +

+
+
+
+ +
+ Example +

The following example is a long dialogue with the shell. Commands + starting with > are inputs to the shell. All other lines + are output from the shell. All commands in this example are explained at the end of the dialogue. + .

+
+strider 1> erl
+Erlang (BEAM) emulator version 5.3 [hipe] [threads:0]
+
+Eshell V5.3  (abort with ^G)
+1>Str = "abcd".
+"abcd"
+2> L = length(Str).
+4
+3> Descriptor = {L, list_to_atom(Str)}.
+{4,abcd}
+4> L. 
+4
+5> b().
+Descriptor = {4,abcd}
+L = 4
+Str = "abcd"
+ok
+6> f(L). 
+ok
+7> b().
+Descriptor = {4,abcd}
+Str = "abcd"
+ok
+8> f(L).
+ok
+9> {L, _} = Descriptor.
+{4,abcd}
+10> L.
+4
+11> {P, Q, R} = Descriptor.
+** exception error: no match of right hand side value {4,abcd}
+12> P.
+* 1: variable 'P' is unbound **
+13> Descriptor.
+{4,abcd}
+14>{P, Q} = Descriptor.
+{4,abcd}
+15> P.
+4
+16> f().
+ok
+17> put(aa, hello).
+undefined
+18> get(aa).
+hello
+19> Y = test1:demo(1).
+11
+20> get().
+[{aa,worked}]
+21> put(aa, hello).
+worked
+22> Z = test1:demo(2).
+** exception error: no match of right hand side value 1
+     in function  test1:demo/1
+23> Z.
+* 1: variable 'Z' is unbound **
+24> get(aa).
+hello
+25> erase(), put(aa, hello).
+undefined
+26> spawn(test1, demo, [1]).
+<0.57.0>
+27> get(aa).
+hello
+28> io:format("hello hello\ ").
+hello hello ok
+29> e(28).
+hello hello ok
+30> v(28).
+ok
+31> c(ex).
+{ok,ex}
+32> rr(ex).
+[rec]
+33> rl(rec).
+-record(rec,{a,b = val()}).
+ok
+34> #rec{}.
+** exception error: undefined shell command val/0
+35> #rec{b = 3}.
+#rec{a = undefined,b = 3}
+36> rp(v(-1)).
+#rec{a = undefined,b = 3}
+ok
+37> rd(rec, {f = orddict:new()}).
+rec
+38> #rec{}.
+#rec{f = []}
+ok
+39> rd(rec, {c}), A.
+* 1: variable 'A' is unbound **
+40> #rec{}.
+#rec{c = undefined}
+ok
+41> test1:loop(0).
+Hello Number: 0
+Hello Number: 1
+Hello Number: 2
+Hello Number: 3
+
+User switch command
+ --> i
+ --> c
+.
+.
+.
+Hello Number: 3374
+Hello Number: 3375
+Hello Number: 3376
+Hello Number: 3377
+Hello Number: 3378
+** exception exit: killed
+42> E = ets:new(t, []).
+17
+43> ets:insert({d,1,2}).
+** exception error: undefined function ets:insert/1
+44> ets:insert(E, {d,1,2}).
+** exception error: argument is of wrong type
+     in function  ets:insert/2
+        called as ets:insert(16,{d,1,2})
+45> f(E).
+ok
+46> catch_exception(true).
+false
+47> E = ets:new(t, []).
+18
+48> ets:insert({d,1,2}).
+* exception error: undefined function ets:insert/1
+49> ets:insert(E, {d,1,2}).
+true
+50> halt().
+strider 2>
+
+ +
+ Comments +

Command 1 sets the variable Str to the string + "abcd". +

+

Command 2 sets L to the length of the string evaluating + the BIF atom_to_list. +

+

Command 3 builds the tuple Descriptor. +

+

Command 4 prints the value of the variable L. +

+

Command 5 evaluates the internal shell command b(), which + is an abbreviation of "bindings". This prints + the current shell variables and their bindings. The ok at + the end is the return value of the b() function. +

+

Command 6 f(L) evaluates the internal shell command + f(L) (abbreviation of "forget"). The value of the variable + L is removed. +

+

Command 7 prints the new bindings. +

+

Command 8 has no effect since L has no value.

+

Command 9 performs a pattern matching operation on + Descriptor, binding a new value to L. +

+

Command 10 prints the current value of L. +

+

Command 11 tries to match {P, Q, R} against + Descriptor which is {4, abc}. The match fails and + none of the new variables become bound. The printout starting + with "** exception error:" is not the value of the + expression (the expression had no value because its evaluation + failed), but rather a warning printed by the system to inform + the user that an error has occurred. The values of the other + variables (L, Str, etc.) are unchanged. +

+

Commands 12 and 13 show that P is unbound because the + previous command failed, and that Descriptor has not + changed. +

+

Commands 14 and 15 show a correct match where P and + Q are bound. +

+

Command 16 clears all bindings. +

+

The next few commands assume that test1:demo(X) is + defined in the following way:

+
+demo(X) ->
+    put(aa, worked),
+    X = 1,
+    X + 10.    
+

Commands 17 and 18 set and inspect the value of the item + aa in the process dictionary. +

+

Command 19 evaluates test1:demo(1). The evaluation + succeeds and the changes made in the process dictionary become + visible to the shell. The new value of the dictionary item + aa can be seen in command 20. +

+

Commands 21 and 22 change the value of the dictionary item + aa to hello and call test1:demo(2). Evaluation + fails and the changes made to the dictionary in + test1:demo(2), before the error occurred, are discarded. +

+

Commands 23 and 24 show that Z was not bound and that the + dictionary item aa has retained its original value. +

+

Commands 25, 26 and 27 show the effect of evaluating + test1:demo(1) in the background. In this case, the + expression is evaluated in a newly spawned process. Any + changes made in the process dictionary are local to the newly + spawned process and therefore not visible to the shell. +

+

Commands 28, 29 and 30 use the history facilities of the shell. +

+

Command 29 is e(28). This re-evaluates command + 28. Command 30 is v(28). This uses the value (result) of + command 28. In the cases of a pure function (a function + with no side effects), the result is the same. For a function + with side effects, the result can be different. +

+

The next few commands show some record manipulation. It is + assumed that ex.erl defines a record like this:

+
+-record(rec, {a, b = val()}).
+
+val() ->
+    3.    
+

Commands 31 and 32 compiles the file ex.erl and reads + the record definitions in ex.beam. If the compiler did not + output any record definitions on the BEAM file, rr(ex) + tries to read record definitions from the source file instead. +

+

Command 33 prints the definition of the record named + rec. +

+

Command 34 tries to create a rec record, but fails + since the function val/0 is undefined. Command 35 shows + the workaround: explicitly assign values to record fields that + cannot otherwise be initialized. +

+

Command 36 prints the newly created record using record + definitions maintained by the shell. +

+

Command 37 defines a record directly in the shell. The + definition replaces the one read from the file ex.beam. +

+

Command 38 creates a record using the new definition, and + prints the result. +

+

Command 39 and 40 show that record definitions are updated + as side effects. The evaluation of the command fails but + the definition of rec has been carried out. +

+

For the next command, it is assumed that test1:loop(N) is + defined in the following way:

+
+loop(N) ->
+    io:format("Hello Number: ~w~n", [N]), 
+    loop(N+1).
+

Command 41 evaluates test1:loop(0), which puts the + system into an infinite loop. At this point the user types + Control G, which suspends output from the current process, + which is stuck in a loop, and activates JCL mode. In JCL + mode the user can start and stop jobs. +

+

In this particular case, the i command ("interrupt") is + used to terminate the looping program, and the c command + is used to connect to the shell again. Since the process was + running in the background before we killed it, there will be + more printouts before the "** exception exit: killed" + message is shown. +

+

Command 42 creates an ETS table.

+

Command 43 tries to insert a tuple into the ETS table but the + first argument (the table) is missing. The exception kills the + evaluator process.

+

Command 44 corrects the mistake, but the ETS table has been + destroyed since it was owned by the killed evaluator process.

+

Command 46 sets the exception handling of the evaluator process + to true. The exception handling can also be set when + starting Erlang, like this: erl -stdlib shell_catch_exception + true.

+

Command 48 makes the same mistake as in command 43, but this time + the evaluator process lives on. The single star at the beginning + of the printout signals that the exception has been caught.

+

Command 49 successfully inserts the tuple into the ETS table.

+

The halt() command exits the Erlang runtime system. +

+
+ +
+ JCL Mode +

When the shell starts, it starts a single evaluator + process. This process, together with any local processes which + it spawns, is referred to as a job. Only the current job, + which is said to be connected, can perform operations + with standard IO. All other jobs, which are said to be detached, are + blocked if they attempt to use standard IO. +

+

All jobs which do not use standard IO run in the normal way. +

+

The shell escape key ^G (Control G) detaches the current job + and activates JCL mode. The JCL mode prompt is "-->". If "?" is entered at the prompt, the following help message is + displayed:

+
+          --> ?
+          c [nn]            - connect to job
+          i [nn]            - interrupt job
+          k [nn]            - kill job
+          j                 - list all jobs
+          s [shell]         - start local shell
+          r [node [shell]]  - start remote shell
+          q        - quit erlang
+          ? | h             - this message    
+

The JCL commands have the following meaning:

+ + c [nn] + +

Connects to job number ]]> or the current + job. The standard shell is resumed. Operations which use + standard IO by the current job will be interleaved with + user inputs to the shell. +

+
+ i [nn] + +

Stops the current evaluator process for job number + nn or the current job, but does not kill the shell + process. Accordingly, any variable bindings and the process dictionary + will be preserved and the job can be connected again. + This command can be used to interrupt an endless loop. +

+
+ k [nn] + +

Kills job number nn or the current + job. All spawned processes in the job are + killed, provided they have not evaluated the + group_leader/1 BIF and are located on + the local machine. Processes spawned on remote nodes will + not be killed. +

+
+ j + +

Lists all jobs. A list of all known jobs is + printed. The current job name is prefixed with '*'. +

+
+ s + +

Starts a new job. This will be assigned the new index + [nn] which can be used in references. +

+
+ s [shell] + +

Starts a new job. This will be assigned the new index + [nn] which can be used in references. + If the optional argument shell is given, it is assumed + to be a module that implements an alternative shell. +

+
+ r [node] + +

Starts a remote job on node. This is used in + distributed Erlang to allow a shell running on one node to + control a number of applications running on a network of + nodes. + If the optional argument shell is given, it is assumed + to be a module that implements an alternative shell. +

+
+ q + +

Quits Erlang. Note that this option is disabled if + Erlang is started with the ignore break, +Bi, + system flag (which may be useful e.g. when running + a restricted shell, see below). +

+
+ ? + +

Displays this message.

+
+
+

It is possible to alter the behavior of shell escape by means + of the STDLIB application variable shell_esc. The value of + the variable can be either jcl (erl -stdlib shell_esc jcl) + or abort (erl -stdlib shell_esc abort). The + first option sets ^G to activate JCL mode (which is also + default behavior). The latter sets ^G to terminate the current + shell and start a new one. JCL mode cannot be invoked when + shell_esc is set to abort.

+

If you want an Erlang node to have a remote job active from the start + (rather than the default local job), you start Erlang with the + -remsh flag. Example: erl -sname this_node -remsh other_node@other_host

+
+ +
+ Restricted Shell +

The shell may be started in a + restricted mode. In this mode, the shell evaluates a function call + only if allowed. This feature makes it possible to, for example, + prevent a user from accidentally calling a function from the + prompt that could harm a running system (useful in combination + with the the system flag +Bi).

+

When the restricted shell evaluates an expression and + encounters a function call or an operator application, + it calls a callback function (with + information about the function call in question). This callback + function returns true to let the shell go ahead with the + evaluation, or false to abort it. There are two possible + callback functions for the user to implement:

+

local_allowed(Func, ArgList, State) -> {true,NewState} | {false,NewState}

+

to determine if the call to the local function Func + with arguments ArgList should be allowed.

+

non_local_allowed(FuncSpec, ArgList, State) -> {true,NewState} | {false,NewState} | {{redirect,NewFuncSpec,NewArgList},NewState}

+

to determine if the call to non-local function + FuncSpec ({Module,Func} or a fun) with arguments + ArgList should be allowed. The return value + {redirect,NewFuncSpec,NewArgList} can be used to let + the shell evaluate some other function than the one specified by + FuncSpec and ArgList.

+

These callback functions are in fact called from local and + non-local evaluation function handlers, described in the + erl_eval + manual page. (Arguments in ArgList are evaluated before the + callback functions are called.)

+

The State argument is a tuple + {ShellState,ExprState}. The return value NewState + has the same form. This may be used to carry a state between calls + to the callback functions. Data saved in ShellState lives + through an entire shell session. Data saved in ExprState + lives only through the evaluation of the current expression.

+

There are two ways to start a restricted shell session:

+ + Use the STDLIB application variable restricted_shell + and specify, as its value, the name of the callback + module. Example (with callback functions implemented in + callback_mod.erl): $ erl -stdlib restricted_shell callback_mod + From a normal shell session, call function + shell:start_restricted/1. This exits the current evaluator + and starts a new one in restricted mode. + +

Notes:

+ + When restricted shell mode is activated or + deactivated, new jobs started on the node will run in restricted + or normal mode respectively. + If restricted mode has been enabled on a + particular node, remote shells connecting to this node will also + run in restricted mode. + The callback functions cannot be used to allow or disallow + execution of functions called from compiled code (only functions + called from expressions entered at the shell prompt). + +

Errors when loading the callback module is handled in different + ways depending on how the restricted shell is activated:

+ + If the restricted shell is activated by setting the kernel + variable during emulator startup and the callback module cannot be + loaded, a default restricted shell allowing only the commands + q() and init:stop() is used as fallback. + If the restricted shell is activated using + shell:start_restricted/1 and the callback module cannot be + loaded, an error report is sent to the error logger and the call + returns {error,Reason}. + +
+ + + history(N) -> integer() + Sets the number of previous commands to keep + + N = integer() + + +

Sets the number of previous commands to keep in the + history list to N. The previous number is returned. + The default number is 20.

+
+
+ + results(N) -> integer() + Sets the number of previous results to keep + + N = integer() + + +

Sets the number of results from previous commands to keep in + the history list to N. The previous number is returned. + The default number is 20.

+
+
+ + catch_exception(Bool) -> Bool + Sets the exception handling of the shell + + Bool = bool() + + +

Sets the exception handling of the evaluator process. The + previous exception handling is returned. The default + (false) is to kill the evaluator process when an + exception occurs, which causes the shell to create a new + evaluator process. When the exception handling is set to + true the evaluator process lives on which means that + for instance ports and ETS tables as well as processes + linked to the evaluator process survive the exception.

+
+
+ + start_restricted(Module) -> ok | {error, Reason} + Exits a normal shell and starts a restricted shell. + + Module = atom() + Reason = atom() + + +

Exits a normal shell and starts a restricted + shell. Module specifies the callback module for the + functions local_allowed/3 and non_local_allowed/3. + The function is meant to be called from the shell.

+

If the callback module cannot be loaded, an error tuple is + returned. The Reason in the error tuple is the one + returned by the code loader when trying to load the code of the callback + module.

+
+
+ + stop_restricted() -> ok + Exits a restricted shell and starts a normal shell. + +

Exits a restricted shell and starts a normal shell. The function + is meant to be called from the shell.

+
+
+
+
+ -- cgit v1.2.3