LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 843|回复: 4

一个设置时区的脚本

[复制链接]
发表于 2005-7-19 14:39:55 | 显示全部楼层 |阅读模式
[php]
#! /bin/sh

# '@(#)tzselect.ksh        1.7'

# Ask the user about the time zone, and output the resulting TZ value to stdout.
# Interact with the user via stderr and stdin.

# Contributed by Paul Eggert <eggert@twinsun.com>.

# Porting notes:
#
# This script requires several features of the Korn shell.
# If your host lacks the Korn shell,
# you can use either of the following free programs instead:
#
#        <a href=ftp://ftp.gnu.org/pub/gnu/>
#        Bourne-Again shell (bash)
#        </a>
#
#        <a href=ftp://ftp.cs.mun.ca/pub/pdksh/pdksh.tar.gz>
#        Public domain ksh
#        </a>
#
# This script also uses several features of modern awk programs.
# If your host lacks awk, or has an old awk that does not conform to Posix.2,
# you can use either of the following free programs instead:
#
#        <a href=ftp://ftp.gnu.org/pub/gnu/>
#        GNU awk (gawk)
#        </a>
#
#        <a href=ftp://ftp.whidbey.net/pub/brennan/>
#        mawk
#        </a>

if [ "${1}" != "" ] ; then
  if [ "${1}" = "-show" ] ; then
    MYTZVAL=`ls -l /etc/localtime | awk '{print $11}' | sed 's/[/]usr[/]share[/]zoneinfo[/]//g'`
    if [ -z "${MYTZVAL}" ] ; then
      echo "Time zone is not set." 2>&1
      exit 1
    else
      echo "${MYTZVAL}" 2>&1
    fi
  else
    echo "Usage: timezone [-show | --help]"
  fi
  exit 0
fi
                                    

# Specify default values for environment variables if they are unset.
: ${AWK=awk}
: ${TZDIR=/usr/share/zoneinfo}
: ${POSIX_TZ=0}

# Check for awk Posix compliance.
($AWK -v x=y 'BEGIN { exit 123 }') </dev/null >/dev/null 2>&1
[ $? = 123 ] || {
        echo >&2 "$0: Sorry, your \`$AWK' program is not Posix compatible."
        exit 1
}

# Make sure the tables are readable.
TZ_COUNTRY_TABLE=$TZDIR/iso3166.tab
TZ_ZONE_TABLE=$TZDIR/zone.tab
for f in $TZ_COUNTRY_TABLE $TZ_ZONE_TABLE
do
        <$f || {
                echo >&2 "$0: time zone files are not set up correctly"
                exit 1
        }
done

newline='
'
IFS=$newline


# Work around a bug in bash 1.14.7 and earlier, where $PS3 is sent to stdout.
case $(echo 1 | (select x in x; do break; done) 2>/dev/null) in
?*) PS3='------------------------------------------------------------------
Your choice: '
esac


# Begin the main loop.  We come back here if the user wants to retry.
while

        echo >&2 'Identify a location' \
                'so that time zone rules can be set correctly.'

        continent=
        country=
        region=


        # Ask the user for continent or ocean.

        echo >&2 'Select a continent or ocean.'

        select continent in \
            Africa \
            Americas \
            Antarctica \
            'Arctic Ocean' \
            Asia \
            'Atlantic Ocean' \
            Australia \
            Europe \
            'Indian Ocean' \
            'Pacific Ocean' \
            'none - I want to specify the time zone using the Posix TZ format.' \
            'cancel - I want to quit without changing the time zone.'
        do
            case $continent in
            '')
                echo >&2 'Enter a number in range.';;
            ?*)
                case $continent in
                Americas) continent=America;;
                *' '*) continent=$(expr "$continent" : '\([^ ]*\)')
                esac
                break
            esac
        done
        case $continent in
        '')
                exit 1;;
        cancel)
                exit 1;;
        none)
                # Ask the user for a Posix TZ string.  Check that it conforms.
                while
                        echo >&2 'Enter the desired value' \
                                'of the TZ environment variable.'
                        echo >&2 'For example, GST-10 is a zone named GST' \
                                'that is 10 hours ahead (east) of UTC.'
                        echo >&2 'Enter "cancel" to quit without setting the time zone.'
                        read TZ
                        if [ "${TZ}" = "cancel" ] ; then
                            exit 1
                        fi
                        $AWK -v TZ="$TZ" 'BEGIN {
                                tzname = "[^-+,0-9][^-+,0-9][^-+,0-9]+"
                                time = "[0-2]?[0-9](:[0-5][0-9](:[0-5][0-9])?)?"
                                offset = "[-+]?" time
                                date = "(J?[0-9]+|M[0-9]+\.[0-9]+\.[0-9]+)"
                                datetime = "," date "(/" time ")?"
                                tzpattern = "^(:.*|" tzname offset "(" tzname \
                                  "(" offset ")?(" datetime datetime ")?)?)$"
                                if (TZ ~ tzpattern) exit 1
                                exit 0
                        }'
                do
                        echo >&2 "\`$TZ' is not a conforming" \
                                'Posix time zone string.'
                done
                POSIX_TZ=1
                TZ_for_date=$TZ;;
        *)
                # Get list of names of countries in the continent or ocean.
                countries=$($AWK -F'\t' \
                        -v continent="$continent" \
                        -v TZ_COUNTRY_TABLE="$TZ_COUNTRY_TABLE" \
                '
                        /^#/ { next }
                        $3 ~ ("^" continent "/") {
                                if (!cc_seen[$1]++) cc_list[++ccs] = $1
                        }
                        END {
                                while (getline <TZ_COUNTRY_TABLE) {
                                        if ($0 !~ /^#/) cc_name[$1] = $2
                                }
                                for (i = 1; i <= ccs; i++) {
                                        country = cc_list
                                        if (cc_name[country]) {
                                          country = cc_name[country]
                                        }
                                        print country
                                }
                        }
                ' <$TZ_ZONE_TABLE | sort -f)


                # If there's more than one country, ask the user which one.
                case $countries in
                *"$newline"*)
                        echo >&2 'Select a country.'
                        select country in $countries cancel
                        do
                            case $country in
                            '') echo >&2 'Enter a number in range.';;
                            ?*) break
                            esac
                        done

                        case $country in
                        '') exit 1 ;;
                        cancel) exit 1
                        esac;;
                *)
                        country=$countries
                esac


                # Get list of names of time zone rule regions in the country.
                regions=$($AWK -F'\t' \
                        -v country="$country" \
                        -v TZ_COUNTRY_TABLE="$TZ_COUNTRY_TABLE" \
                '
                        BEGIN {
                                cc = country
                                while (getline <TZ_COUNTRY_TABLE) {
                                        if ($0 !~ /^#/  &&  country == $2) {
                                                cc = $1
                                                break
                                        }
                                }
                        }
                        $1 == cc { print $4 }
                ' <$TZ_ZONE_TABLE)


                # If there's more than one region, ask the user which one.
                case $regions in
                *"$newline"*)
                        echo >&2 'Select one of the following' \
                                'time zone regions.'
                        select region in $regions cancel
                        do
                                case $region in
                                '') echo >&2 'Enter a number in range.';;
                                ?*) break
                                esac
                        done
                        case $region in
                        '') exit 1 ;;
                        cancel) exit 1
                        esac;;
                *)
                        region=$regions
                esac

                # Determine TZ from country and region.
                TZ=$($AWK -F'\t' \
                        -v country="$country" \
                        -v region="$region" \
                        -v TZ_COUNTRY_TABLE="$TZ_COUNTRY_TABLE" \
                '
                        BEGIN {
                                cc = country
                                while (getline <TZ_COUNTRY_TABLE) {
                                        if ($0 !~ /^#/  &&  country == $2) {
                                                cc = $1
                                                break
                                        }
                                }
                        }
                        $1 == cc && $4 == region { print $3 }
                ' <$TZ_ZONE_TABLE)

                # Make sure the corresponding zoneinfo file exists.
                TZ_for_date=$TZDIR/$TZ
                <$TZ_for_date || {
                        echo >&2 "$0: time zone files are not set up correctly"
                        exit 1
                }
        esac


        # Use the proposed TZ to output the current date relative to UTC.
        # Loop until they agree in seconds.
        # Give up after 8 unsuccessful tries.

        extra_info=
        for i in 1 2 3 4 5 6 7 8
        do
                TZdate=$(LANG=C TZ="$TZ_for_date" date)
                UTdate=$(LANG=C TZ=UTC0 date)
                TZsec=$(expr "$TZdate" : '.*:\([0-5][0-9]\)')
                UTsec=$(expr "$UTdate" : '.*:\([0-5][0-9]\)')
                case $TZsec in
                $UTsec)
                        extra_info="
Local time is now:        $TZdate.
Universal Time is now:        $UTdate."
                        break
                esac
        done


        # Output TZ info and ask the user to confirm.

        echo >&2 ""
        echo >&2 "The following information has been given:"
        echo >&2 ""
        case $country+$region in
        ?*+?*)        echo >&2 "        $country$newline        $region";;
        ?*+)        echo >&2 "        $country";;
        +)        echo >&2 "        TZ='$TZ'"
        esac
        echo >&2 ""
        echo >&2 "Therefore TZ='$TZ' will be used.$extra_info"
        echo >&2 "Is the above information OK?"

        ok=
        select ok in Yes No Cancel
        do
            case $ok in
            '') echo >&2 'Enter 1 for Yes, 2 for No, or 3 for Cancel.';;
            ?*) break
            esac
        done
        case $ok in
        '') exit 1;;
        Cancel) exit 1;;
        Yes) break
        esac
do :
done

case $SHELL in
*csh) file=.login line="setenv TZ '$TZ'";;
*) file=.profile line="TZ='$TZ'; export TZ"
esac


   
# echo >&2 "
# You can make this change permanent for yourself by appending the line
#         $line
# to the file '$file' in your home directory; then log out and log in again.
#
# Here is that TZ value again, this time on standard output so that you
# can use the $0 command in shell scripts:"

rm -f /etc/localtime

if [ "$POSIX_TZ" == "0" ]; then
        ln -s "${TZDIR}/${TZ}" /etc/localtime
else
        ln -s "${TZDIR}/Etc/${TZ}" /etc/localtime
fi

echo $TZ > /etc/localtime.tz

hwclock --systohc --localtime
hwclock --hctosys --localtime
echo "Updating time zone succeded." 2>&1

# echo "$TZ"
[/php]



版主加精
发表于 2005-7-20 08:08:55 | 显示全部楼层
1. 普通用户运行会报错,因为没有权限。所以,如果script是只能让root运行的,在前面加上对用户ID的判断。这样在最后就不会报错还说“succeeded".另外最后这个"succeded"单词拼错了。
整体来说这个script做得很不错,感谢你分享!
回复 支持 反对

使用道具 举报

 楼主| 发表于 2005-7-20 15:53:36 | 显示全部楼层
不是我写的,我是拿来给大家看看的,我也是烤回来的.
回复 支持 反对

使用道具 举报

发表于 2005-7-21 01:46:06 | 显示全部楼层
Post by genv
不是我写的,我是拿来给大家看看的,我也是烤回来的.

哦是这样,那我把我的回帖改一下。
回复 支持 反对

使用道具 举报

发表于 2005-7-22 00:08:36 | 显示全部楼层
Post by yongjian
Intel 3.4G/E, 2G DDR2, HD 800G, OS: Ubuntu 5.04, SLES9, Mandriva. VMware Guest: RHEL4, RHEL3 WS, Gentoo, Ubuntu live, Sun10, Feather, DSL, KNOPPIX, SLES9, SLAX, Gnoppix, WinXP
Lot fun...
No monitor -> has monitor now 20" DELL

真是系统狂人
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表