# sh scripting question



## jwnetsource (Jul 28, 2009)

FreeBSD 8.0-RELEASE
$SHELL: csh

With this simple script:

```
#! /bin/sh
# jw-rotate.sh
# Apache log rotation script for multiple virtual domains

VIRTUAL_HOST_NAME=( x1.com x2.com x3.com )
echo ${VIRTUAL_HOST_NAME[@]}
```
Running 


```
./jw-rotate.sh
```

outputs


```
./jw-rotate.sh: 5: Syntax error: word unexpected (expecting ")")
```

Running


```
bash ./jw-rotate.sh
```

outputs


```
x1.com x2.com x3.com
```


Apparently, from post elsewhere, this is a FreeBSD anomaly, does not error on Linux.

I'm confused.  Can anyone provide an explanation for this?

Thanks

J


----------



## aragon (Jul 28, 2009)

It's not a FreeBSD anomaly.  Bourne shell simply doesn't support arrays.  Bash shell does support arrays.  You will either need to use bash for your script or not use arrays.

What is arguably an anomaly is linux's practise of making /bin/sh link to a bash shell.  /bin/sh _should_ be a Bourne shell, and linking it to a bash shell confuses people like you into thinking arrays are valid syntax for /bin/sh.


----------



## aragon (Jul 28, 2009)

BTW, before you write a rotation script, you might want to take a look at newsyslog(8).


----------



## estrabd (Jul 28, 2009)

newsyslog++


----------



## DutchDaemon (Jul 28, 2009)

aragon said:
			
		

> What is arguably an anomaly is linux's practise of making /bin/sh link to a bash shell.



Hear hear. Not arguably: _definitely_!


----------



## danger@ (Jul 28, 2009)

and maybe sysutils/logrotate too.


----------



## jwnetsource (Jul 28, 2009)

Thanks for the reply/education.

I am currently using both newsyslog and apache rotatelogs for different purposes.  Both have a limitation (I think) that inspires me to right my own log rotation script.

I have several virtual hosts on the same server, managed for different clients, with separate access_log files.  I am writing the script to move and compress the log file with the following naming convention:

  domain_access_log-2009-07-27

which is the domain name and date prepended and appended to access_log.

Thanks again


----------



## anomie (Jul 28, 2009)

jwnetsource said:
			
		

> I am currently using both newsyslog and apache rotatelogs for different purposes.  Both have a limitation (I think) that inspires me to right my own log rotation script.
> 
> I have several virtual hosts on the same server, managed for different clients, with separate access_log files.  I am writing the script to move and compress the log file with the following naming convention:
> 
> domain_access_log-2009-07-27



You can still do this without using arrays. Assuming newsyslog(8) is not going to meet your needs, try something like: 

```
#!/bin/sh

#
# Functions
#
rotate() {

  # do stuff to rotate ${_logname} here...
  # name it with `date` somehow...
  # ...

}

#
# Main logic
#
_logname=/var/log/something1 ]
```


----------



## aragon (Jul 28, 2009)

One can also do this:


```
domains="domain1.com domain2.com domain3.com"
for domain in ${domains}; do
  rotate ${domain}
done
```


----------



## rbelk (Jul 29, 2009)

Aragon, how did you get my log rotation script 

Seriously, that is the way I write my Apache log rotation scripts for multiple domains. But sh and bash does have a 256 byte variable size limit! Just keep a watch for that and everything will be OK.


----------



## bb (Jul 29, 2009)

Or that:


```
while read domain
do
  if [ -n "$domain" -a "x${domain#[#]}" = "x$domain" ]
  then
    rotate "${domain}"
  fi
done <<'EOF'

# comment
domain1.com
domain2.com
domain3.com

EOF
```


----------



## lme@ (Jul 29, 2009)

jwnetsource said:
			
		

> FreeBSD 8.0-RELEASE
> $SHELL: csh



I wonder where you got 8.0-RELEASE from. ;-)


----------



## jwnetsource (Jul 30, 2009)

lme@ said:
			
		

> I wonder where you got 8.0-RELEASE from. ;-)



First, thanks all for the log rotation advice!

Regarding FreeBSD 8.0-RELEASE, keeping in mind that I wander through Unix with both fear and excitement(kinda like spelunking with weak batteries), and that I was going through life fat, dumb, and happy, running 7.0-RELEASE.

Then one day, for kicks and grins, I decided to customize my kernel.  So, I updated all the ports:


```
*default host=cvsup.FreeBSD.org
    *default base=/usr
    *default prefix=/usr
    *default release=cvs tag=RELENG_7
    *default delete use-rel-suffix
    *default compress
    *default tag=.
    src-all
    ports-all tag=.
    doc-all tag=.
    cvsroot-all
```


Then I tweaked make.conf and rebuilt world and kernel as per the handbook.

Somewhere throughout this process the /etc/motd file was modified (not by me) and, Voila, when I rebooted and logged in, the console said I had FreeBSD 8.0-RELEASE.


Do I have FreeBSD 8.0-RELEASE or is it still 7?


----------



## jwnetsource (Jul 30, 2009)

oops, it's FreeBSD 8.0-CURRENT


----------



## blah (Jul 30, 2009)

*jwnetsource*, that's no surprising. You've specified *tag* with collection **default* twice.





			
				jwnetsource said:
			
		

> ```
> *default release=cvs tag=RELENG_7
> *default tag=.
> ```


The last one takes precedence.


----------



## SirDice (Jul 30, 2009)

Yep, tag=. at this moment is 8.0-CURRENT. When 8.0 gets released it may be a good idea to change it to RELENG_8, which will keep you on 8.0-STABLE. Or to RELENG_8_0, which will keep you on 8.0-RELEASE.


----------



## jwnetsource (Jul 30, 2009)

Sorry to be off topic, but since we are:

I'll leave it as is until 8 is released, then change to read:


```
*default host=cvsup.FreeBSD.org
    *default base=/usr
    *default prefix=/usr
    *default release=cvs tag=RELENG_8_0
    *default delete use-rel-suffix
    *default compress
    *default tag=.
    src-all
    doc-all tag=.
    cvsroot-all
```

Thanks much


----------



## DutchDaemon (Jul 30, 2009)

Take out 
	
	



```
*default tag=.
```


----------



## jwnetsource (Jul 30, 2009)

Oops again.  

I have another question pertaining to this topic shift, which I moved to:

http://forums.freebsd.org/showthread.php?t=5912

Thanks for your help.


----------



## Bill Evans at Mariposa (Nov 27, 2015)

bb said:


> Or that:
> 
> 
> ```
> ...


This is actually a quite useful workaround for the lack of arrays in the Bourne shell.  Consider the following method of passing through two parallel lists more than once.  Disclaimer: I haven't actually run the code that I'm typing here, but I've run code quite like it. Note that it comes dangerously close to making function `onepass` a higher order function.

```
#!/bin/sh

onepass()
{
  if [ "$1" = firstsecond ]
  then
    while read FIRST
    do
      read SECOND
      $2 $FIRST $SECOND
    done
  elif [ "$1" = secondfirst ]
  then
    while read FIRST
    do
      read SECOND
      $2 $SECOND $FIRST
    done
  elif [ "$1" = secondonly ]
  then
    while read FIRST
    do
      read SECOND
      $2 $SECOND
    done
  elif [ "$1" = echosecond ]
  then
    while read FIRST
    do
      read SECOND
      echo $SECOND
    done
  else
    echo "invalid verb $1 to function onepass" >&2
    exit 1
  fi<<EOD
alpha-first
alpha-second
beta-first
beta-second
gamma-first
gamma-second
delta-first
delta-second
epsilon-first
epsilon-second
EOD
}

onepass firstsecond "cp -av"
onepass secondonly "chown home:home -v"
onepass secondonly "chmod 755 -v"
mkdir something.d
cp -av $(onepass echosecond) something.d
```


----------

