ovs-ctl.in: Add manager after restoring flows.
[sliver-openvswitch.git] / utilities / ovs-ctl.in
1 #! /bin/sh
2 # Copyright (C) 2009, 2010, 2011, 2012, 2013 Nicira, Inc.
3 #
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at:
7 #
8 #     http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15
16 case $0 in
17     */*) dir0=`echo "$0" | sed 's,/[^/]*$,,'` ;;
18     *) dir0=./ ;;
19 esac
20 . "$dir0/ovs-lib" || exit 1
21
22 for dir in "$sbindir" "$bindir" /sbin /bin /usr/sbin /usr/bin; do
23     case :$PATH: in
24         *:$dir:*) ;;
25         *) PATH=$PATH:$dir ;;
26     esac
27 done
28
29 ## ----- ##
30 ## start ##
31 ## ----- ##
32
33 insert_mod_if_required () {
34     # If openvswitch is already loaded then we're done.
35     test -e /sys/module/openvswitch -o -e /sys/module/openvswitch_mod && \
36      return 0
37
38     # Load openvswitch.  If that's successful then we're done.
39     action "Inserting openvswitch module" modprobe openvswitch && return 0
40
41     # If the bridge module is loaded, then that might be blocking
42     # openvswitch.  Try to unload it, if there are no bridges.
43     test -e /sys/module/bridge || return 1
44     bridges=`echo /sys/class/net/*/bridge | sed 's,/sys/class/net/,,g;s,/bridge,,g'`
45     if test "$bridges" != "*"; then
46         log_warning_msg "not removing bridge module because bridges exist ($bridges)"
47         return 1
48     fi
49     action "removing bridge module" rmmod bridge || return 1
50
51     # Try loading openvswitch again.
52     action "Inserting openvswitch module" modprobe openvswitch
53 }
54
55 ovs_vsctl () {
56     ovs-vsctl --no-wait "$@"
57 }
58
59 ovsdb_tool () {
60     ovsdb-tool -vconsole:off "$@"
61 }
62
63 create_db () {
64     action "Creating empty database $DB_FILE" ovsdb_tool create "$DB_FILE" "$DB_SCHEMA"
65 }
66
67 upgrade_db () {
68     schemaver=`ovsdb_tool schema-version "$DB_SCHEMA"`
69     if test ! -e "$DB_FILE"; then
70         log_warning_msg "$DB_FILE does not exist"
71         install -d -m 755 -o root -g root `dirname $DB_FILE`
72         create_db
73     elif test X"`ovsdb_tool needs-conversion "$DB_FILE" "$DB_SCHEMA"`" != Xno; then
74         # Back up the old version.
75         version=`ovsdb_tool db-version "$DB_FILE"`
76         cksum=`ovsdb_tool db-cksum "$DB_FILE" | awk '{print $1}'`
77         backup=$DB_FILE.backup$version-$cksum
78         action "Backing up database to $backup" cp "$DB_FILE" "$backup" || return 1
79
80         # Compact database.  This is important if the old schema did not enable
81         # garbage collection (i.e. if it did not have any tables with "isRoot":
82         # true) but the new schema does.  In that situation the old database
83         # may contain a transaction that creates a record followed by a
84         # transaction that creates the first use of the record.  Replaying that
85         # series of transactions against the new database schema (as "convert"
86         # does) would cause the record to be dropped by the first transaction,
87         # then the second transaction would cause a referential integrity
88         # failure (for a strong reference).
89         #
90         # Errors might occur on an Open vSwitch downgrade if ovsdb-tool doesn't
91         # understand some feature of the schema used in the OVSDB version that
92         # we're downgrading from, so we don't give up on error.
93         action "Compacting database" ovsdb_tool compact "$DB_FILE"
94
95         # Upgrade or downgrade schema.
96         if action "Converting database schema" ovsdb_tool convert "$DB_FILE" "$DB_SCHEMA"; then
97             :
98         else
99             log_warning_msg "Schema conversion failed, using empty database instead"
100             rm -f "$DB_FILE"
101             create_db
102         fi
103     fi
104 }
105
106 set_system_ids () {
107     set ovs_vsctl set Open_vSwitch .
108
109     OVS_VERSION=`ovs-vswitchd --version | sed 's/.*) //;1q'`
110     set "$@" ovs-version="$OVS_VERSION"
111
112     case $SYSTEM_ID in
113         random)
114             id_file=$etcdir/system-id.conf
115             uuid_file=$etcdir/install_uuid.conf
116             if test -e "$id_file"; then
117                 SYSTEM_ID=`cat "$id_file"`
118             elif test -e "$uuid_file"; then
119                 # Migrate from old file name.
120                 . "$uuid_file"
121                 SYSTEM_ID=$INSTALLATION_UUID
122                 echo "$SYSTEM_ID" > "$id_file"
123             elif SYSTEM_ID=`uuidgen`; then
124                 echo "$SYSTEM_ID" > "$id_file"
125             else
126                 log_failure_msg "missing uuidgen, could not generate system ID"
127             fi
128             ;;
129
130         '')
131             log_failure_msg "system ID not configured, please use --system-id"
132             ;;
133
134         *)
135             ;;
136     esac
137     set "$@" external-ids:system-id="\"$SYSTEM_ID\""
138
139     if test X"$SYSTEM_TYPE" != X; then
140         set "$@" system-type="\"$SYSTEM_TYPE\""
141     else
142         log_failure_msg "no default system type, please use --system-type"
143     fi
144
145     if test X"$SYSTEM_VERSION" != X; then
146         set "$@" system-version="\"$SYSTEM_VERSION\""
147     else
148         log_failure_msg "no default system version, please use --system-version"
149     fi
150
151     action "Configuring Open vSwitch system IDs" "$@" $extra_ids
152 }
153
154 check_force_cores () {
155     if test X"$FORCE_COREFILES" = Xyes; then
156         ulimit -c 67108864
157     fi
158 }
159
160 start_ovsdb () {
161     check_force_cores
162
163     if daemon_is_running ovsdb-server; then
164         log_success_msg "ovsdb-server is already running"
165     else
166         # Create initial database or upgrade database schema.
167         upgrade_db || return 1
168
169         # Start ovsdb-server.
170         set ovsdb-server "$DB_FILE"
171         for db in $EXTRA_DBS; do
172             case $db in
173                 /*) ;;
174                 *) db=$dbdir/$db ;;
175             esac
176
177             if test ! -f "$db"; then
178                 log_warning_msg "$db (from \$EXTRA_DBS) does not exist."
179             elif ovsdb-tool db-version "$db" >/dev/null; then
180                 set "$@" "$db"
181             else
182                 log_warning_msg "$db (from \$EXTRA_DBS) cannot be read as a database (see error message above)"
183             fi
184         done
185         set "$@" -vconsole:emer -vsyslog:err -vfile:info
186         set "$@" --remote=punix:"$DB_SOCK"
187         set "$@" --private-key=db:Open_vSwitch,SSL,private_key
188         set "$@" --certificate=db:Open_vSwitch,SSL,certificate
189         set "$@" --bootstrap-ca-cert=db:Open_vSwitch,SSL,ca_cert
190         start_daemon "$OVSDB_SERVER_PRIORITY" "$OVSDB_SERVER_WRAPPER" "$@" \
191             || return 1
192
193         # Initialize database settings.
194         ovs_vsctl -- init -- set Open_vSwitch . db-version="$schemaver" \
195             || return 1
196         set_system_ids || return 1
197         if test X"$DELETE_BRIDGES" = Xyes; then
198             for bridge in `ovs_vsctl list-br`; do
199         ovs_vsctl del-br $bridge
200             done
201         fi
202     fi
203 }
204
205 add_managers () {
206     # Now that ovs-vswitchd has started and completed its initial
207     # configuration, tell ovsdb-server to conenct to the remote managers.  We
208     # used to do this at ovsdb-server startup time, but waiting for
209     # ovs-vswitchd to finish configuring means that remote managers see less
210     # churn in the database at startup or restart.  (For example, managers
211     # won't briefly see empty datapath-id or ofport columns for records that
212     # exist at startup.)
213     action "Enabling remote OVSDB managers" \
214         ovs-appctl -t ovsdb-server ovsdb-server/add-remote \
215             db:Open_vSwitch,Open_vSwitch,manager_options
216 }
217
218 start_forwarding () {
219     check_force_cores
220
221     insert_mod_if_required || return 1
222
223     if daemon_is_running ovs-vswitchd; then
224         log_success_msg "ovs-vswitchd is already running"
225     else
226         # Increase the limit on the number of open file descriptors.
227         # On Linux, ovs-vswitchd needs about one file descriptor per
228         # switch port, so this allows a very large number of switch
229         # ports.
230         ulimit -n 5000
231
232             # Start ovs-vswitchd.
233             set ovs-vswitchd unix:"$DB_SOCK"
234             set "$@" -vconsole:emer -vsyslog:err -vfile:info
235             if test X"$MLOCKALL" != Xno; then
236                 set "$@" --mlockall
237             fi
238             start_daemon "$OVS_VSWITCHD_PRIORITY" "$OVS_VSWITCHD_WRAPPER" "$@"
239     fi
240 }
241
242 ## ---- ##
243 ## stop ##
244 ## ---- ##
245
246 stop_ovsdb () {
247     stop_daemon ovsdb-server
248 }
249
250 stop_forwarding () {
251     stop_daemon ovs-vswitchd
252 }
253
254 ## ----------------- ##
255 ## force-reload-kmod ##
256 ## ----------------- ##
257
258 internal_interfaces () {
259     # Outputs a list of internal interfaces:
260     #
261     #   - There is an internal interface for every bridge, whether it
262     #     has an Interface record or not and whether the Interface
263     #     record's 'type' is properly set or not.
264     #
265     #   - There is an internal interface for each Interface record whose
266     #     'type' is 'internal'.
267     #
268     # But ignore interfaces that don't really exist.
269     for d in `(ovs_vsctl --bare \
270                 -- --columns=name find Interface type=internal \
271                     -- list-br) | sort -u`
272     do
273         if test -e "/sys/class/net/$d"; then
274                 printf "%s " "$d"
275             fi
276     done
277 }
278
279 ovs_save () {
280     bridges=`ovs_vsctl -- --real list-br`
281     if [ -n "${bridges}" ] && \
282         "$datadir/scripts/ovs-save" "$1" ${bridges} > "$2"; then
283         chmod +x "$2"
284         return 0
285     fi
286     [ -z "${bridges}" ] && return 0
287 }
288
289 save_ofports_if_required () {
290     # Save ofports if we are upgrading from a pre-1.10 branch.
291     case `ovs-appctl version | sed 1q` in
292         "ovs-vswitchd (Open vSwitch) 1."[0-9].*)
293             action "Saving ofport values" ovs_save save-ofports \
294                 "${script_ofports}"
295             ;;
296     esac
297 }
298
299 save_interfaces () {
300     "$datadir/scripts/ovs-save" save-interfaces ${ifaces} \
301         > "${script_interfaces}"
302 }
303
304 restore_ofports () {
305     [ -x "${script_ofports}" ] && \
306         action "Restoring ofport values" "${script_ofports}"
307 }
308
309 restore_flows () {
310     [ -x "${script_flows}" ] && \
311         action "Restoring saved flows" "${script_flows}"
312 }
313
314 restore_interfaces () {
315     [ ! -x "${script_interfaces}" ] && return 0
316     action "Restoring interface configuration" "${script_interfaces}"
317     rc=$?
318     if test $rc = 0; then
319         level=debug
320     else
321         level=err
322     fi
323     log="logger -p daemon.$level -t ovs-save"
324     $log "interface restore script exited with status $rc:"
325     $log -f "$script_interfaces"
326 }
327
328 init_restore_scripts () {
329     script_interfaces=`mktemp`
330     script_flows=`mktemp`
331     script_ofports=`mktemp`
332     trap 'rm -f "${script_interfaces}" "${script_flows}" "${script_ofports}"' 0
333 }
334
335 force_reload_kmod () {
336     ifaces=`internal_interfaces`
337     action "Detected internal interfaces: $ifaces" true
338
339     init_restore_scripts
340
341     action "Saving flows" ovs_save save-flows "${script_flows}"
342
343     save_ofports_if_required
344
345     # Restart the database first, since a large database may take a
346     # while to load, and we want to minimize forwarding disruption.
347     stop_ovsdb
348     start_ovsdb
349
350     # Restore of ofports should happen before vswitchd is restarted.
351     restore_ofports
352
353     stop_forwarding
354
355     if action "Saving interface configuration" save_interfaces; then
356         :
357     else
358         log_warning_msg "Failed to save configuration, not replacing kernel module"
359         start_forwarding
360         add_managers
361         exit 1
362     fi
363     chmod +x "$script_interfaces"
364
365     for dp in `ovs-dpctl dump-dps`; do
366         action "Removing datapath: $dp" ovs-dpctl del-dp "$dp"
367     done
368
369     # try both old and new names in case this is post upgrade
370     if test -e /sys/module/openvswitch_mod; then
371         action "Removing openvswitch module" rmmod openvswitch_mod
372     elif test -e /sys/module/openvswitch; then
373         action "Removing openvswitch module" rmmod openvswitch
374     fi
375
376     start_forwarding
377
378     restore_flows
379     add_managers
380
381     restore_interfaces
382
383     "$datadir/scripts/ovs-check-dead-ifs"
384 }
385
386 ## ------- ##
387 ## restart ##
388 ## ------- ##
389
390 save_interfaces_if_required () {
391     # Save interfaces if we are upgrading from a pre-1.10 branch.
392     case `ovs-appctl version | sed 1q` in
393         "ovs-vswitchd (Open vSwitch) 1."[0-9].*)
394             ifaces=`internal_interfaces`
395             action "Detected internal interfaces: $ifaces" true
396             if action "Saving interface configuration" save_interfaces; then
397                 chmod +x "$script_interfaces"
398             fi
399             ;;
400     esac
401 }
402
403 restart () {
404     if daemon_is_running ovsdb-server && daemon_is_running ovs-vswitchd; then
405         init_restore_scripts
406         save_interfaces_if_required
407         action "Saving flows" ovs_save save-flows "${script_flows}"
408         save_ofports_if_required
409     fi
410
411     # Restart the database first, since a large database may take a
412     # while to load, and we want to minimize forwarding disruption.
413     stop_ovsdb
414     start_ovsdb
415
416     # Restore of ofports, if required, should happen before vswitchd is
417     # restarted.
418     restore_ofports
419
420     stop_forwarding
421     start_forwarding
422
423     # Restore the saved flows.
424     restore_flows
425     add_managers
426
427     # Restore the interfaces if required. Return true even if restore fails.
428     restore_interfaces || true
429 }
430
431 ## --------------- ##
432 ## enable-protocol ##
433 ## --------------- ##
434
435 enable_protocol () {
436     # Translate the protocol name to a number, because "iptables -n -L" prints
437     # some protocols by name (despite the -n) and therefore we need to look for
438     # both forms.
439     #
440     # (iptables -S output is more uniform but old iptables doesn't have it.)
441     protonum=`grep "^$PROTOCOL[         ]" /etc/protocols | awk '{print $2}'`
442     if expr X"$protonum" : X'[0-9]\{1,\}$' > /dev/null; then :; else
443         log_failure_msg "unknown protocol $PROTOCOL"
444         return 1
445     fi
446
447     name=$PROTOCOL
448     match="(\$2 == \"$PROTOCOL\" || \$2 == $protonum)"
449     insert="iptables -I INPUT -p $PROTOCOL"
450     if test X"$DPORT" != X; then
451         name="$name to port $DPORT"
452         match="$match && /dpt:$DPORT/"
453         insert="$insert --dport $DPORT"
454     fi
455     if test X"$SPORT" != X; then
456         name="$name from port $SPORT"
457         match="$match && /spt:$SPORT/"
458         insert="$insert --sport $SPORT"
459     fi
460     insert="$insert -j ACCEPT"
461
462     if (iptables -n -L INPUT) >/dev/null 2>&1; then
463         if iptables -n -L INPUT | awk "$match { n++ } END { exit n == 0 }"
464         then
465             # There's already a rule for this protocol.  Don't override it.
466             log_success_msg "iptables already has a rule for $name, not explicitly enabling"
467         else
468             action "Enabling $name with iptables" $insert
469         fi
470     elif (iptables --version) >/dev/null 2>&1; then
471         action "cannot list iptables rules, not adding a rule for $name"
472     else
473         action "iptables binary not installed, not adding a rule for $name"
474     fi
475 }
476
477 ## ---- ##
478 ## main ##
479 ## ---- ##
480
481 set_defaults () {
482     SYSTEM_ID=
483
484     DELETE_BRIDGES=no
485
486     DAEMON_CWD=/
487     FORCE_COREFILES=yes
488     MLOCKALL=yes
489     OVSDB_SERVER_PRIORITY=-10
490     OVS_VSWITCHD_PRIORITY=-10
491     OVSDB_SERVER_WRAPPER=
492     OVS_VSWITCHD_WRAPPER=
493
494     DB_FILE=$dbdir/conf.db
495     DB_SOCK=$rundir/db.sock
496     DB_SCHEMA=$datadir/vswitch.ovsschema
497     EXTRA_DBS=
498
499     PROTOCOL=gre
500     DPORT=
501     SPORT=
502
503     type_file=$etcdir/system-type.conf
504     version_file=$etcdir/system-version.conf
505
506     if test -e "$type_file" ; then
507         SYSTEM_TYPE=`cat $type_file`
508         SYSTEM_VERSION=`cat $version_file`
509     elif (lsb_release --id) >/dev/null 2>&1; then
510         SYSTEM_TYPE=`lsb_release --id -s`
511         system_release=`lsb_release --release -s`
512         system_codename=`lsb_release --codename -s`
513         SYSTEM_VERSION="${system_release}-${system_codename}"
514     else
515         SYSTEM_TYPE=unknown
516         SYSTEM_VERSION=unknown
517     fi
518 }
519
520 usage () {
521     set_defaults
522     cat <<EOF
523 $0: controls Open vSwitch daemons
524 usage: $0 [OPTIONS] COMMAND
525
526 This program is intended to be invoked internally by Open vSwitch startup
527 scripts.  System administrators should not normally invoke it directly.
528
529 Commands:
530   start              start Open vSwitch daemons
531   stop               stop Open vSwitch daemons
532   restart            stop and start Open vSwitch daemons
533   status             check whether Open vSwitch daemons are running
534   version            print versions of Open vSwitch daemons
535   load-kmod          insert modules if not already present
536   force-reload-kmod  save OVS network device state, stop OVS, unload kernel
537                      module, reload kernel module, start OVS, restore state
538   enable-protocol    enable protocol specified in options with iptables
539   help               display this help message
540
541 One of the following options is required for "start", "restart" and "force-reload-kmod":
542   --system-id=UUID   set specific ID to uniquely identify this system
543   --system-id=random  use a random but persistent UUID to identify this system
544
545 Other important options for "start", "restart" and "force-reload-kmod":
546   --system-type=TYPE  set system type (e.g. "XenServer")
547   --system-version=VERSION  set system version (e.g. "5.6.100-39265p")
548   --external-id="key=value"
549                      add given key-value pair to Open_vSwitch external-ids
550   --delete-bridges   delete all bridges just before starting ovs-vswitchd
551
552 Less important options for "start", "restart" and "force-reload-kmod":
553   --daemon-cwd=DIR               set working dir for OVS daemons (default: $DAEMON_CWD)
554   --no-force-corefiles           do not force on core dumps for OVS daemons
555   --no-mlockall                  do not lock all of ovs-vswitchd into memory
556   --ovsdb-server-priority=NICE   set ovsdb-server's niceness (default: $OVSDB_SERVER_PRIORITY)
557   --ovs-vswitchd-priority=NICE   set ovs-vswitchd's niceness (default: $OVS_VSWITCHD_PRIORITY)
558
559 Debugging options for "start", "restart" and "force-reload-kmod":
560   --ovsdb-server-wrapper=WRAPPER
561   --ovs-vswitchd-wrapper=WRAPPER
562   --ovs-vswitchd-wrapper=WRAPPER
563      run specified daemon under WRAPPER (either 'valgrind' or 'strace')
564
565 File location options:
566   --db-file=FILE     database file name (default: $DB_FILE)
567   --db-sock=SOCKET   JSON-RPC socket name (default: $DB_SOCK)
568   --db-schema=FILE   database schema file name (default: $DB_SCHEMA)
569
570 Options for "enable-protocol":
571   --protocol=PROTOCOL  protocol to enable with iptables (default: gre)
572   --sport=PORT       source port to match (for tcp or udp protocol)
573   --dport=PORT       ddestination port to match (for tcp or udp protocol)
574
575 Other options:
576   -h, --help                  display this help message
577   -V, --version               display version information
578
579 Default directories with "configure" option and environment variable override:
580   logs: @LOGDIR@ (--with-logdir, OVS_LOGDIR)
581   pidfiles and sockets: @RUNDIR@ (--with-rundir, OVS_RUNDIR)
582   conf.db: @DBDIR@ (--with-dbdir, OVS_DBDIR)
583   system configuration: @sysconfdir@ (--sysconfdir, OVS_SYSCONFDIR)
584   data files: @pkgdatadir@ (--pkgdatadir, OVS_PKGDATADIR)
585   user binaries: @bindir@ (--bindir, OVS_BINDIR)
586   system binaries: @sbindir@ (--sbindir, OVS_SBINDIR)
587
588 Please report bugs to bugs@openvswitch.org (see REPORTING-BUGS for details).
589 EOF
590
591     exit 0
592 }
593
594 set_option () {
595     var=`echo "$option" | tr abcdefghijklmnopqrstuvwxyz- ABCDEFGHIJKLMNOPQRSTUVWXYZ_`
596     eval set=\${$var+yes}
597     eval old_value=\$$var
598     if test X$set = X || \
599         (test $type = bool && \
600         test X"$old_value" != Xno && test X"$old_value" != Xyes); then
601         echo >&2 "$0: unknown option \"$arg\" (use --help for help)"
602         return
603     fi
604     eval $var=\$value
605 }
606
607 daemons () {
608     echo ovsdb-server ovs-vswitchd
609 }
610
611 set_defaults
612 extra_ids=
613 command=
614 for arg
615 do
616     case $arg in
617         -h | --help)
618             usage
619             ;;
620         -V | --version)
621             echo "$0 (Open vSwitch) $VERSION"
622             exit 0
623             ;;
624         --external-id=*)
625             value=`expr X"$arg" : 'X[^=]*=\(.*\)'`
626             case $value in
627                 *=*)
628                     extra_ids="$extra_ids external-ids:$value"
629                     ;;
630                 *)
631                     echo >&2 "$0: --external-id argument not in the form \"key=value\""
632                     exit 1
633                     ;;
634             esac
635             ;;
636         --[a-z]*=*)
637             option=`expr X"$arg" : 'X--\([^=]*\)'`
638             value=`expr X"$arg" : 'X[^=]*=\(.*\)'`
639             type=string
640             set_option
641             ;;
642         --no-[a-z]*)
643             option=`expr X"$arg" : 'X--no-\(.*\)'`
644             value=no
645             type=bool
646             set_option
647             ;;
648         --[a-z]*)
649             option=`expr X"$arg" : 'X--\(.*\)'`
650             value=yes
651             type=bool
652             set_option
653             ;;
654         -*)
655             echo >&2 "$0: unknown option \"$arg\" (use --help for help)"
656             exit 1
657             ;;
658         *)
659             if test X"$command" = X; then
660                 command=$arg
661             else
662                 echo >&2 "$0: exactly one non-option argument required (use --help for help)"
663                 exit 1
664             fi
665             ;;
666     esac
667 done
668 case $command in
669     start)
670         start_ovsdb
671         start_forwarding
672         add_managers
673         ;;
674     stop)
675         stop_forwarding
676         stop_ovsdb
677         ;;
678     restart)
679         restart
680         ;;
681     status)
682         rc=0
683         for daemon in `daemons`; do
684             daemon_status $daemon || rc=$?
685         done
686         exit $rc
687         ;;
688     version)
689         for daemon in `daemons`; do
690             $daemon --version
691         done
692         ;;
693     force-reload-kmod)
694             force_reload_kmod
695         ;;
696     load-kmod)
697         insert_mod_if_required
698         ;;
699     enable-protocol)
700         enable_protocol
701         ;;
702     help)
703         usage
704         ;;
705     '')
706         echo >&2 "$0: missing command name (use --help for help)"
707         exit 1
708         ;;
709     *)
710         echo >&2 "$0: unknown command \"$command\" (use --help for help)"
711         exit 1
712         ;;
713 esac