oracle修改c root,从新发现Oracle太美之root.sh

重新发现Oracle太美之root.sh

如果你执行下以下命令基本上会在Oracle软件目录下会发现两个root.sh的脚本

[oracle@rh64 Templates]$ find /u01/ -name root.sh |xargs ls -ltr

-rwxrwx--- 1 oracle oinstall  10 May 14 02:37 /u01/app/db11g/product/11.2.0/dbhome_1/inventory/Templates/root.sh

-rwxr-x--- 1 oracle oinstall 512 May 14 02:47 /u01/app/db11g/product/11.2.0/dbhome_1/root.sh

第一个脚本里面没啥东西,我们今天主要来研究下第二个root.sh是干啥用的,也就是我们安装软件后需要运行的这个root.sh的主要作用。

[oracle@rh64 ~]$ cat /u01/app/db11g/product/11.2.0/dbhome_1/root.sh

#!/bin/sh

. /u01/app/db11g/product/11.2.0/dbhome_1/install/utl/rootmacro.sh "$@"

. /u01/app/db11g/product/11.2.0/dbhome_1/install/utl/rootinstall.sh

/u01/app/db11g/product/11.2.0/dbhome_1/install/unix/rootadd.sh

#

# Root Actions related to network

#

/u01/app/db11g/product/11.2.0/dbhome_1/network/install/sqlnet/setowner.sh

#

# Invoke standalone rootadd_rdbms.sh

#

/u01/app/db11g/product/11.2.0/dbhome_1/rdbms/install/rootadd_rdbms.sh

/u01/app/db11g/product/11.2.0/dbhome_1/rdbms/install/rootadd_filemap.sh

[oracle@rh64 ~]$

可以看到上面脚本里面包含了6个小的脚本,我们一一来分析下看看这个root.sh里面的脚本都是干啥的。

1.第一个脚本

[oracle@rh64 ~]$ cat /u01/app/db11g/product/11.2.0/dbhome_1/install/utl/rootmacro.sh

#!/bin/sh

#

# $Id: rootmacro.sbs /st_buildtools_11.2.0/2 2012/11/06 02:43:45 rmallego Exp $

# Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved.

#

# root.sh

#

# This script is intended to be run by root.  The script contains

# all the product installation actions that require root privileges.

#

# IMPORTANT NOTES - READ BEFORE RUNNING SCRIPT

#

# (1) ORACLE_HOME and ORACLE_OWNER can be defined in user's

#     environment to override default values defined in this script.

#

# (2) The environment variable LBIN (defined within the script) points to

#     the default local bin area.  Three executables will be moved there as

#     part of this script execution.

#

# (3) Define (if desired) LOG variable to name of log file.

#

-------->>>上面明确说明运行脚本之前ORACLE_HOME,ORACLE_OWNER一定要设置

AWK=/bin/awk

CAT=/bin/cat

CHGRP=/bin/chgrp

CHOWN=/bin/chown

CHMOD=/bin/chmod

CP=/bin/cp

DIFF=/usr/bin/diff

ECHO=echo

GREP=/bin/grep

LBIN=/usr/local/bin

MKDIR=/bin/mkdir

ORATABLOC=/etc

ORATAB=${ORATABLOC}/oratab

RM=/bin/rm

SED=/bin/sed

UNAME=/bin/uname

DATE=/bin/date

TEE=/usr/bin/tee

TMPORATB=/var/tmp/oratab$$

if [ `$UNAME` = "SunOS" ]

then

GREP=/usr/xpg4/bin/grep

fi

# Variable based on installation

OUI_SILENT=false

#

# Default values set by Installer

#

ORACLE_HOME=/u01/app/db11g/product/11.2.0/dbhome_1

ORACLE_OWNER=oracle

OSDBA_GROUP=oinstall

MAKE=/usr/bin/make

#

# conditional code execution starts. This set of code is invoked exactly once

# regardless of number of scripts that source rootmacro.sh

if [ "x$WAS_ROOTMACRO_CALL_MADE" = "x" ]; then

WAS_ROOTMACRO_CALL_MADE=YES ; export WAS_ROOTMACRO_CALL_MADE

LOG=${ORACLE_HOME}/install/root_`$UNAME -n`_`$DATE +%F_%H-%M-%S`.log ; export LOG

#

# Parse argument

#

while [ $# -gt 0 ]

do

case $1 in

-silent)  SILENT_F=1;;         # silent is set to true

-crshome) shift; CRSHOME=$1; export CRSHOME;;  # CRSHOME is set

-bindir) shift; LBIN=$1; export LBIN;;

esac;

shift

done

#

# If LOG is not set, then send output to /dev/null

#

if [ "x${LOG}" = "x" -o "${LOG}" = "" ];then

LOG=/dev/null

else

$CP $LOG ${LOG}0 2>/dev/null

$ECHO "" > $LOG

fi

#

# Silent variable is set based on :

# if OUI_SILENT is true or if SILENT_F is 1

#

if [ "${OUI_SILENT}" = "true" -o "$SILENT_F" ]

then

SILENT=1

else

SILENT=0

fi

if [ $SILENT -eq 1 ]

then

$ECHO "Check $LOG for the output of root script"

exec > $LOG 2>&1

else

mkfifo $LOG.pipe

tee < $LOG.pipe $LOG &

exec &> $LOG.pipe

rm $LOG.pipe

fi

#

# check for valid crshome

#

if [ "$CRSHOME" -a ! -d "$CRSHOME" ]; then

$ECHO "ERROR: CRS home $CRSHOME is not a valid directory." | $TEE -a $LOG

exit 1

fi

----->>>检查是否设置crshome

#

# Determine how to suppress newline with $ECHO command.

#

case ${N}$C in

"") if $ECHO "\c"| $GREP c >/dev/null 2>&1;then

N='-n'

else

C='\c'

fi;;

esac

#

# check for zero UID

#

RUID=`/usr/bin/id|$AWK -F\( '{print $1}'|$AWK -F= '{print $2}'`

if [ $RUID -ne 0 ];then

$ECHO "You must be logged in as user with UID as zero (e.g. root user) to run root configuration script."| $TEE -a $LOG

$ECHO "Log in as user with UID as zero (e.g. root user) and restart root configuration script execution."| $TEE -a $LOG

exit 1

fi

----->>>检查是否以root用户执行操作

#

# Display abort message on interrupt.

#

trap '$ECHO "Oracle root script execution aborted!"| $TEE -a $LOG;exit' 1 2 3 15

#

# Check for $LOG file existence and if it exists, change the ownership to oracle_owner:oracle_owner_group and permissions to 600

#

if [ -f $LOG ];then

$CHOWN $ORACLE_OWNER:$OSDBA_GROUP $LOG

$CHMOD 600 $LOG

fi

fi

#conditional code execution ends

------>>>>修改权限,修改宿主,拥有者,日志权限为600

可以看到上述脚本主要是检查是否为root用户,修改宿主,并且需要在环境变量有相应的ORACLE_HOME,ORACLE_OWNER等

[oracle@rh64 ~]$

第二个脚本

[oracle@rh64 ~]$ cat /u01/app/db11g/product/11.2.0/dbhome_1/install/utl/rootinstall.sh

$ECHO "Performing root user operation for Oracle 11g "

$ECHO ""

$ECHO "The following environment variables are set as:"

$ECHO "    ORACLE_OWNER= $ORACLE_OWNER"

$ECHO "    ORACLE_HOME=  $ORACLE_HOME"

#

# Get name of local bin directory

#

saveLBIN=$LBIN

retry='r'

while [ "$retry" = "r" ]

do

if [ $SILENT -eq 0 ]

then

LBIN=$saveLBIN

$ECHO ""

$ECHO $N "Enter the full pathname of the local bin directory: $C"

DEFLT=${LBIN}; . $ORACLE_HOME/install/utl/read.sh; LBIN=$RDVAR

fi

if [ ! -d $LBIN ];then

$ECHO "Creating ${LBIN} directory..."

$MKDIR -p ${LBIN} 2>&1

$CHMOD 755 ${LBIN} 2>&1

fi

if [ ! -w $LBIN ]

then

if [ $SILENT -eq 0 ]

then

$ECHO ""

$ECHO $N "$LBIN is read only.  Continue without copy (y/n) or retry (r)? $C"

DEFLT='y' ; . $ORACLE_HOME/install/utl/read.sh ; retry=$RDVAR

else

retry='y'  # continue without copy

fi

else

retry='y'

fi

done

if [ "$retry" = "n" ] ; then

$ECHO "Warning: Script terminated by user."

exit 1

fi

#

# Move files to LBIN, and set permissions

#

DBHOME=$ORACLE_HOME/bin/dbhome

ORAENV=$ORACLE_HOME/bin/oraenv

CORAENV=$ORACLE_HOME/bin/coraenv

FILES="$DBHOME $ORAENV $CORAENV"

----->>>这里就是移动这几个文件,然后设置相应的权限。上面三个环境变量比较熟悉,我们需要升级备份的时候通常需要备份这些东西,

其实这个东西可以从$ORACLE_HOME/bin下拷贝过到/usr/local/bin,所以屌丝们以后可以不用担心了~~~

if [ -w $LBIN ]

then

for f in $FILES ; do

if [ -f $f ] ; then

$CHMOD 755 $f  2>&1 2>> $LOG

short_f=`$ECHO $f | $SED 's;.*/;;'`

lbin_f=$LBIN/$short_f

if [ -f $lbin_f -a $SILENT -eq 0 ] ; then

DIFF_STATUS=`$DIFF $f $lbin_f`

if [ $? -ne 0 ] ; then

# The contents of $lbin_f and $f are different (User updated $lbin_f)

# Prompt user before overwriting $lbin_f.

$ECHO $n "The file \"$short_f\" already exists in $LBIN.  Overwrite it? (y/n) $C"

DEFLT='n'; . $ORACLE_HOME/install/utl/read.sh; OVERWRITE=$RDVAR

else

# The contents of $lbin_f and $f are identical. Don't overwrite.

$ECHO "The contents of \"$short_f\" have not changed. No need to overwrite."

OVERWRITE='n';

fi

else

OVERWRITE='y';

fi

if [ "$OVERWRITE" = "y" -o "$OVERWRITE" = "Y" ] ; then

$CP $f $LBIN  2>&1 2>>  $LOG

$CHMOD 755 $lbin_f  2>&1 2>> $LOG

$CHOWN $ORACLE_OWNER $LBIN/`$ECHO $f | $AWK -F/ '{print $NF}'` 2>&1 2>> $LOG

$ECHO "   Copying $short_f to $LBIN ..."

fi

fi

done

------>>>注意这几个权限为755,下面是对比下$ORACLE_HOME和/usr/local/bin下几个文件权限和宿主的区别

[oracle@rh64 bin]$ ls -ltr dbhome

-rwxr-xr-x 1 oracle oinstall 2415 Jan  1  2000 dbhome

[oracle@rh64 bin]$ ls -tlr coraenv

-rwxr-xr-x 1 oracle oinstall 5778 Jan  1  2000 coraenv

[oracle@rh64 bin]$ ls -ltr oraenv

-rwxr-xr-x 1 oracle oinstall 6183 Jan  1  2000 oraenv

[root@rh64 bin]# ls -ltr dbhome

-rwxr-xr-x 1 oracle root 2415 Oct 30  2013 dbhome

[root@rh64 bin]# ls -ltr oraenv

-rwxr-xr-x 1 oracle root 6183 Oct 30  2013 oraenv

[root@rh64 bin]# ls -ltr coraenv

-rwxr-xr-x 1 oracle root 5778 Oct 30  2013 coraenv

------->>>>看到了吗?权限都是755,但是/usr/local/bin的拥有者为oracle:root,如果不慎丢失需要手工拷过来的时候记得需要改成755,oracle:root

else

$ECHO ""

$ECHO "Warning: $LBIN is read only. No files will be copied."

fi

$ECHO ""

#

# Make sure an oratab file exists on this system

#

# Variable to determine whether oratab is new or not; default is true

NEW="true"

if [ ! -s ${ORATAB} ];then

$ECHO ""

$ECHO "Creating ${ORATAB} file..."

if [ ! -d ${ORATABLOC} ];then

$MKDIR -p ${ORATABLOC}

fi

$CAT <> ${ORATAB}

#

# This file is used by ORACLE utilities.  It is created by root.sh

# and updated by either Database Configuration Assistant while creating

# a database or ASM Configuration Assistant while creating ASM instance.

# A colon, ':', is used as the field terminator.  A new line terminates

# the entry.  Lines beginning with a pound sign, '#', are comments.

#

# Entries are of the form:

#   \$ORACLE_SID:\$ORACLE_HOME::

#

# The first and second fields are the system identifier and home

# directory of the database respectively.  The third filed indicates

# to the dbstart utility that the database should , "Y", or should not,

# "N", be brought up at system boot time.

#

# Multiple entries with the same \$ORACLE_SID are not allowed.

#

#

!

else

# Oratab file exists; this is not a new installation on this system.

# We check if temporary install/oratab exists, and then check if the entry

# in temporary install/oratab has been added to the oratab file.

# In case of patchset this is usually the case, and we don't want to reappend

# the same entry to oratab again.

if [ -f $ORACLE_HOME/install/oratab ]

then

TMP_ENTRY=`$GREP "${ORACLE_HOME}" $ORACLE_HOME/install/oratab`

FOUND=`$GREP "${TMP_ENTRY}" ${ORATAB}`

if [ -n "${FOUND}" ]

then

NEW="false"

fi

fi

fi

----->>>>注意,我们所有root.sh脚本执行的日志都会在$ORACLE_HOME/install/下面有的,以便我们进行错误定位

$CHOWN $ORACLE_OWNER:$OSDBA_GROUP ${ORATAB}

$CHMOD 664 ${ORATAB}

----->>>/etc/oratab的权限为664

#

# If there is an old entry with no sid and same oracle home,

# that entry will be marked as a comment.

#

FOUND_OLD=`$GREP "^*:${ORACLE_HOME}:" ${ORATAB}`

if [ -n "${FOUND_OLD}" ];then

$SED -e "s?^*:$ORACLE_HOME:?# *:$ORACLE_HOME:?" $ORATAB > $TMPORATB

$CAT $TMPORATB > $ORATAB

$RM -f $TMPORATB 2>/dev/null

fi

$ECHO "Entries will be added to the ${ORATAB} file as needed by"

$ECHO "Database Configuration Assistant when a database is created"

#

# Append the dbca temporary oratab entry to oratab

# In the case of ASM and RAC install, oratab is not yet created when root.sh

# is run, so we need to check for its existence before attempting to append it.

#

if [ -f $ORACLE_HOME/install/oratab -a $NEW = "true" ]

then

$CAT $ORACLE_HOME/install/oratab >> $ORATAB

fi

$ECHO "Finished running generic part of root script."

$ECHO "Now product-specific root actions will be performed."

第三个脚本

[oracle@rh64 ~]$ cat /u01/app/db11g/product/11.2.0/dbhome_1/install/unix/rootadd.sh

#!/bin/sh

#!/usr/bin/sh

ORACLE_HOME=/u01/app/db11g/product/11.2.0/dbhome_1

. $ORACLE_HOME/install/utl/rootmacro.sh

# the following commands need to run as root after installing

# the OEM Daemon

AWK=/usr/bin/awk

CAT=/usr/bin/cat

CHOWN="/usr/bin/chown"

CHMOD="/usr/bin/chmod"

CHMODR="/usr/bin/chmod -R"

CP=/usr/bin/cp

ECHO=/usr/bin/echo

MKDIR=/usr/bin/mkdir

TEE=/usr/bin/tee

RM=/bin/rm

MV=/bin/mv

GREP=/usr/bin/grep

CUT=/bin/cut

SED=/usr/bin/sed

PLATFORM=`uname`

if [ ${PLATFORM} = "Linux" ] ; then

CAT=/bin/cat

CHOWN=/bin/chown

CHMOD=/bin/chmod

CHMODR="/bin/chmod -R"

CP=/bin/cp

ECHO=/bin/echo

MKDIR=/bin/mkdir

GREP=/bin/grep

if [ ! -f $CUT ] ; then

CUT=/usr/bin/cut

fi

SED=/bin/sed

fi

if [ ${PLATFORM} = "SunOS" ] ; then

GREP=/usr/xpg4/bin/grep

fi

if [ ${PLATFORM} = "Darwin" ] ; then

CAT=/bin/cat

CHOWN="/usr/sbin/chown"

CHMOD="/bin/chmod"

CHMODR="/bin/chmod -R"

CP=/bin/cp

ECHO=/bin/echo

MKDIR=/bin/mkdir

CUT=/usr/bin/cut

fi

# change owner and permissions of the remote operations executible

if [ -f  ${ORACLE_HOME}/bin/nmo.0 ];

then

$RM -f ${ORACLE_HOME}/bin/nmo

$CP -p ${ORACLE_HOME}/bin/nmo.0 ${ORACLE_HOME}/bin/nmo

fi

$CHOWN root $ORACLE_HOME/bin/nmo

$CHMOD 4710 $ORACLE_HOME/bin/nmo

# change owner and permissions of the program that does memory computations

if [ -f  ${ORACLE_HOME}/bin/nmb.0 ];

then

$RM -f ${ORACLE_HOME}/bin/nmb

$CP -p ${ORACLE_HOME}/bin/nmb.0 ${ORACLE_HOME}/bin/nmb

fi

$CHOWN root $ORACLE_HOME/bin/nmb

$CHMOD 4710 $ORACLE_HOME/bin/nmb

# change owner and permissions of the storage metrics executible

if [ -f  ${ORACLE_HOME}/bin/nmhs.0 ];

then

$RM -f ${ORACLE_HOME}/bin/nmhs

$CP -p ${ORACLE_HOME}/bin/nmhs.0 ${ORACLE_HOME}/bin/nmhs

fi

$CHOWN root $ORACLE_HOME/bin/nmhs

$CHMOD 4710 $ORACLE_HOME/bin/nmhs

#change permissions on emdctl and emagent

$CHMOD 700 $ORACLE_HOME/bin/emagent

$CHMOD 700 $ORACLE_HOME/bin/emdctl

# change permissions so they are accessible by users from groups

# other than the agent user group.

$CHMOD 755 $ORACLE_HOME/bin

$CHMODR a+rX $ORACLE_HOME/lib

$CHMODR a+rX $ORACLE_HOME/perl

#$CHMODR a+rX $ORACLE_HOME/sysman/admin/scripts

$CHMODR a+rX $ORACLE_HOME/jdk

$CHMOD 755 $ORACLE_HOME/bin/nmocat

#

# Following changes to system executables are needed for getting

# host inventory metrics on HP-UX

#

if [ ${PLATFORM} = "HP-UX" ] ; then

$CHMOD 555 /usr/sbin/swapinfo

#$CHMOD +r /dev/rdsk/*

fi

$ECHO "Finished product-specific root actions."| $TEE -a $LOG

[oracle@rh64 ~]$

第四个脚本:

[oracle@rh64 ~]$ cat /u01/app/db11g/product/11.2.0/dbhome_1/network/install/sqlnet/setowner.sh

#!/bin/sh

ORACLE_HOME=/u01/app/db11g/product/11.2.0/dbhome_1

. $ORACLE_HOME/install/utl/rootmacro.sh

:

if [ ! -d /var/tmp/.oracle ]

then

$MKDIR -p /var/tmp/.oracle;

fi

$CHMOD 01777 /var/tmp/.oracle

$CHOWN root  /var/tmp/.oracle

if [ ! -d /tmp/.oracle ]

then

$MKDIR -p /tmp/.oracle;

fi

$CHMOD 01777 /tmp/.oracle

$CHOWN root  /tmp/.oracle

------->>>这个地方要注意了,这个临时文件的.oracle,有点意思

第五个脚本:

[oracle@rh64 ~]$ cat /u01/app/db11g/product/11.2.0/dbhome_1/rdbms/install/rootadd_rdbms.sh

#!/bin/sh

ORACLE_HOME=/u01/app/db11g/product/11.2.0/dbhome_1

CHOWN=/bin/chown

CHMOD=/bin/chmod

RM=/bin/rm

AWK=/bin/awk

ECHO=/bin/echo

CP=/bin/cp

#

# check for zero UID

#

RUID=`/usr/bin/id|$AWK -F\( '{print $1}'|$AWK -F= '{print $2}'`

if [ $RUID -ne 0 ];then

$ECHO "You must be logged in as user with UID as zero (e.g. root user) to run root.sh."

$ECHO "Log in as user with UID as zero (e.g. root user) and restart root.sh execHTTP/1.1 200 OK

Server: nginx/1.4.2

Date: Fri, 06 Jun 2014 05:15:01 GMT

Content-Type: text/html; charset=utf-8

Content-Length: 42012

Connection: keep-alive

Vary: Accept-Encoding

X-Author: sq_zhuyi

Set-Cookie: uuid=3f61ec2a-463a-482e-873a-251aa91fd176; expires=Sat, 07-Jun-2014 05:13:06 GMT; path=/

Set-Cookie: avh=28635157; expires=Fri, 06-Jun-2014 06:13:06 GMT; path=/

Cache-Control: private, max-age=0, must-revalidate

ETag: "a2e40a6f8b734ae3346dae2d23b93f30"

插入排序:表折半插入 - 自由人的自由结合

- 博客频道 - CSDN.NET

自由人的自由结合

结构、算法、c、c++

131501532.gif目录视图

131501533.gif摘要视图

131501534.gif订阅

有奖征资源,博文分享有内涵

4月推荐博文汇总

CSDN博客支持Windows Live Writer离线写博客啦

插入排序:表折半插入

分类:

数据结构与算法

2014-06-05 17:26

142人阅读

评论(0)

收藏

举报

插入排序二分查找表折半插入pre算法

在前一篇插入排序:表插入中,我们用静态链表的存储方式,直接插入的策略,构建了一种新的插入排序算法:表插入。有人可能会想到:同样是静态链表的形式,为什么不使用更高效的折半插入策略呢?这种想法真的很好,如果做到了,显然是极大的优化。

我在网上还真看到了相关的内容,大家可搜下《表插入方法的改进》,里面有此想法的介绍。这篇博客就是介绍表插入的另一种实现:表折半插入。看完一定让你彻底理解它!

与一般的折半插入相比,有如下的几点变化:

为了实现折半查找,我们对静态链表的节点类型做了一些变化:添加了一个前驱指针。它的意义很显然,以前是high=mid-1,在单向链表中我们是做不到的(其实可以换种方式做到,不过相对麻烦),于是添加一指向其前驱的指针,构成双向链表,方便进行此操作。

while循环的结束条件,有所不同。这个要仔细理解!

其他细节,代码中有详细解释

const int MAX=100;

typedef struct rec

{

int data;

int pre; //前驱

int next; //后继

}Rec;

void InsertSort(int a[], int n) //表折半插入

{

Rec *rec=new Rec[n+1];

for(int i=0; i

{

rec[i+1].data=a[i];

rec[i+1].next=rec[i+1].pre=0;

}

rec[0].data=MAX;

rec[0].next=rec[0].pre=1;

int low,high,mid;

int p,k,l;

for(int i=2; i

{

//根据以下的赋值,我们可以看出,这里使用的是左闭右闭区间

low=rec[0].next; //low指向最小的

high=rec[0].pre; //high指向最大的

l=i-1; //已有序的元素个数

while(low!=0 && high!=0 && rec[low].data<=rec[high].data) //循环结束条件得理解,特别是前两个条件。准确的是,第一个条件可以不要

{

mid=low;

k=1;

l/=2; // l>>=2 减半,为下次循环做好准备

while(k

{

mid=rec[mid].next;

k++;

}

if(rec[i].data

high=rec[mid].pre;

else

low=rec[mid].next;

}

//插入第i个节点,类似于双向链表的插入

rec[rec[low].pre].next=i;

rec[i].pre=rec[low].pre; //添加前驱指针的作用体现在这里

rec[i].next=low;

rec[low].pre=i;

}

//顺着next指针方向打印

printf("表折半插入排序后\n");

p=rec[0].next;

while(p!=0)

{

printf("%-4d",rec[p].data);

p=rec[p].next;

}

printf("\n");

}

仔细看完代码,我想大多数人只剩一个问题可能没明白,那就是while循环的结束条件为什么还得加上low!=0 和high!=0?

为了解释清楚,我们画一个图,图中正在插入i=2的节点:

131501535.png

初始化后,low,mid,high显然都指向1,经过下一步rec[i].data与rec[mid].data比较后,无论结果怎样,循环都应结束。可如果rec[i].data

到此,你应该明白了代码中所有的注释。

测试走起啊……

p.s 对rec数组1-n号元素进行重排也是可以的,做法参照上一篇博客哦,方法一模一样。

转载请注明出处,本文地址:http://blog.csdn.net/zhangxiangdavaid/article/details/28635157

代码就是折腾,越折腾越进步!

文章评论

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值