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