I am creating some Jenkins tokens for githooks and I was using uuidgen.
My coworker said they normally use uuid -v4 and after sudo apt-get-ing uuid, uuid -v4 and uuidgen appear to be the same:
$ uuid -v4
832dce77-ddec-4cc5-9872-47a81456653f
$ uuidgen
a321bc87-a1b5-4cc5-b6b5-feaf3a610ab8
For reference: I am running this on Ubuntu.
What is the difference between them? Are they they same?
tldr; they're both random since uuidgen == uuidgen -r == uuid -v4
The man 1 uuidgen doesn't say so, but uuidgen -t and uuidgen -r are, respectively, producing version 1 ("time and node based") and version 4 ("random data based") UUIDs as dictated by ISO/IEC 11578:1996.
$ { uuidgen -t && uuidgen -r && uuid -v1 && uuid -v4 ; } | xargs -L1 uuid -d
encode: STR: 5f441c74-c63a-11e7-8cb0-0242ac110002
SIV: 126630312945231364299766443008257490946
decode: variant: DCE 1.1, ISO/IEC 11578:1996
version: 1 (time and node based)
content: time: 2017-11-10 17:12:46.679154.0 UTC
clock: 3248 (usually random)
node: 02:42:ac:11:00:02 (local unicast)
encode: STR: d70f042a-c5ca-4726-b259-795e47fd1b95
SIV: 285861988065069261246745478758429170581
decode: variant: DCE 1.1, ISO/IEC 11578:1996
version: 4 (random data based)
content: D7:0F:04:2A:C5:CA:07:26:32:59:79:5E:47:FD:1B:95
(no semantics: random data only)
encode: STR: 5f443b5a-c63a-11e7-8cd2-0242ac110002
SIV: 126630939639996852130686378090112811010
decode: variant: DCE 1.1, ISO/IEC 11578:1996
version: 1 (time and node based)
content: time: 2017-11-10 17:12:46.679945.0 UTC
clock: 3282 (usually random)
node: 02:42:ac:11:00:02 (local unicast)
encode: STR: 09432e97-a1fc-4e05-9492-7c0c11ec0abc
SIV: 12311880856012488273304867468361861820
decode: variant: DCE 1.1, ISO/IEC 11578:1996
version: 4 (random data based)
content: 09:43:2E:97:A1:FC:0E:05:14:92:7C:0C:11:EC:0A:BC
(no semantics: random data only)
References:
https://en.wikipedia.org/wiki/Universally_unique_identifier
https://linux.die.net/man/1/uuidgen
https://linux.die.net/man/1/uuid
For the Mac users out there: BSD uuidgen program on macOS generates UUID v4.
Example:
$ uname
Darwin
$ uuidgen
703849AD-8549-4666-8904-E9AEA8406156
The tool's man page does not state that, but note the 4 on beginning of the 3rd group of characters in this example. This indicates v4 of UUID, as documented in the UUID Wikipedia page or as you can verify using some tool, for example uuidtools.com.
Related
The utility 'sas2ircu' can output multiple lines for every hard drive attached to the host. A sample of the output for a single drive looks like this:
Enclosure # : 5
Slot # : 20
SAS Address : 5003048-0-185f-b21c
State : Ready (RDY)
I have a bash script that executes the sas2ircu command and does the following with the output:
identifies a drive by the RDY string
reads the numerical value of the enclosure (ie, 5) into an array 'enc'
reads the numerical value of the slot (ie, 20) into another array 'slot'
The code I have serves its purpose, but I'm trying to figure out if I can combine it into a single line and run the sas2ircu command once instead of twice.
mapfile -t enc < <(/root/sas2ircu 0 display|grep -B3 RDY|awk '/Enclosure/{print $NF}')
mapfile -t slot < <(/root/sas2ircu 0 display|grep -B2 RDY|awk '/Slot/{print $NF}')
I've done a bunch of reading on awk but I'm still quite novice with it and haven't come up with anything better than what I have. Suggestions?
Should be able to eliminate the grep and combine the awk scripts into a single awk script; the general idea is to capture the enclosure and slot data and then if/when we see State/RDY we print the enclosure and slot to stdout:
awk '/Enclosure/{enclosure=$NF}/Slot/{slot=$NF}/State.*(RDY)/{print enclosure,slot}'
I don't have sas2ircu so I'll simulate some data (based on OP's sample):
$ cat raw.dat
Enclosure # : 5
Slot # : 20
SAS Address : 5003048-0-185f-b21c
State : Ready (RDY)
Enclosure # : 7
Slot # : 12
SAS Address : 5003048-0-185f-b21c
State : Ready (RDY)
Enclosure # : 9
Slot # : 23
SAS Address : 5003048-0-185f-b21c
State : Off (OFF)
Simulating thw sas2ircu call:
$ cat raw.dat | awk '/Enclosure/{enclosure=$NF}/Slot/{slot=$NF}/State.*(RDY)/{print enclosure,slot}'
5 20
7 12
The harder part is going to be reading these into 2 separate arrays and I'm not aware of an easy way to do this with a single command (eg, mapfile doesn't provide a way to split an input file across 2 arrays).
One idea using a bash/while loop:
unset enc slot
while read -r e s
do
enc+=( ${e} )
slot+=( ${s} )
done < <(cat raw.dat | awk '/Enclosure/{enclosure=$NF}/Slot/{slot=$NF}/State.*(RDY)/{print enclosure,slot}')
This generates:
$ typeset -p enc slot
declare -a enc=([0]="5" [1]="7")
declare -a slot=([0]="20" [1]="12")
I have an array
FIRST_ARRAY=(NEWYORK CALIFORNIA TEXAS)
A script that accepts a state can return cities in that state
For example the following would return:
user#localhost:~$ search NEWYORK cities
newyorkcity
buffalo
albany
user#localhost:~$ search CALIFORNIA cities
sanfrancisco
paloalto
losangeles
user#localhost:~$ search TEXAS cities
houston
dallas
austin
I would like to iterate over FIRST_ARRAY
for state in ${FIRST_ARRAY[#]}
do
cities=`search ${FIRST_ARRAY[state]} cities`
ARRAY_$state=($cities}
done
At the end I would expect the following arrays to have been created and they would contain the following values
ARRAY_NEWYORK=(newyorkcity buffalo albany)
ARRAY_CALIFORNIA=(sanfrancisco paloalto losangeles)
ARRAY_TEXAS=(houston dallas austin)
If this works, then for example, I would like to be able to access austin by calling my the dynamically created array in the following way
echo ${ARRAY_TEXAS[2]}
Thanks!
On bash 4.0 or newer, with readarray / mapfile available, the following serves as a terse and correct implementation:
for state in "${FIRST_ARRAY[#]}"; do
readarray -t "ARRAY_$state" < <(search "$state" cities)
done
In bash 4.3, a safe, literal translation of your code is available:
for state in "${FIRST_ARRAY[#]}"; do
readarray -t cities < <(search "$state" cities)
# make "dest" a namevar -- an alias -- for your intended destination
# skip to next state if current state name is invalid
# otherwise we could be assigning to an utterly different "dest"
declare -n dest="ARRAY_$state" || continue
# assign to that namevar
dest=( "$cities" )
# and discard it
unset -n dest
done
In bash 3.x, doing this safely requires some printf %q magic to prepare content to be parsed by eval:
for state in "${FIRST_ARRAY[#]}"; do
# why this, and not array=( $cities )? Try a city with spaces in its name.
# or look at what happens when you have a "city name" that's a wildcard.
cities=( )
while read -r city; do
cities+=( "$city" )
done < <(search "$state" cities)
# generate eval-safe replacement for the cities array
printf -v cities_str '%q ' "${cities[#]}"
# extra paranoia: make sure we fail with a parse error rather than doing something
# unexpected if the state name is not a valid shell variable
printf -v eval_str 'ARRAY_%q=( %s )' "$state" "$cities_str"
eval "$eval_str" # and evaluate that
done
The original question didn't provide an implementation of search to make answers testable. For this answer, I'm using the following:
search() {
case $1 in
NEWYORK) printf '%s\n' newyorkcity buffalo albany ;;
CALIFORNIA) printf '%s\n' sanfrancisco paloalto losangeles ;;
TEXAS) printf '%s\n' houston dallas austin ;;
esac
}
With the above defined, results can be verified as follows:
$ declare -p ARRAY_NEWYORK ARRAY_CALIFORNIA ARRAY_TEXAS
declare -a ARRAY_NEWYORK='([0]="newyorkcity" [1]="buffalo" [2]="albany")'
declare -a ARRAY_CALIFORNIA='([0]="sanfrancisco" [1]="paloalto" [2]="losangeles")'
declare -a ARRAY_TEXAS='([0]="houston" [1]="dallas" [2]="austin")'
data.txt:
hello world
goodbye mars
goodbye perl6
hello perl5
myprog.py:
my $fname = 'data.txt';
my $infile = open($fname, :r, nl => "\n\n");
for $infile.lines(nl => "\n\n") -> $para {
say $para;
say '-' x 10;
}
Actual output:
hello world
----------
goodbye mars
----------
----------
goodbye perl6
----------
back to perl5
----------
Desired output:
hello world
goodbye mars
-----------
goodbye perl6
back to perl5
-----------
...
$ perl6 -v
This is perl6 version 2015.03-21-gcfa4974 built on MoarVM version 2015.03
This appears to be a bug in Rakudo/MoarVM, going back to the fact that MoarVM expects a single grapheme as separator instead of an arbitrary string (cf syncfile.c:38, syncfile.c:119 and syncfile.c:91, which shows that the last character of the separator string is used instead of the whole string).
As a quick workaround (but beware that this reads the entire file into memory), use
$fname.IO.slurp.split("\n\n")
instead of $infile.lines().
You should also file a bug report or ask in #perl6 on Freenode if this is a known issue.
I have a number of raspberry PIs attached to various networks distributed over a large area so this will have to be a remote process. I need to expand the file system so it fills the full 8Gb (currently 2Gb). We use Puppet to distribute updates but I am not sure what the process of commands is.
I know this can be achieved locally using raspi-config but I will need to create a script or send a command to do this over the network.
raspi-config is a shell script. The section on memory expansion is listed below. Here are the basic steps:
Verify that the desired expansion is on a SD card, not external device, and not more than the two normal partitions.
Determine the exact partition and desired partition size. (parted)
Change the size of the partition in the partition table. (This usually requires a reboot to take effect.) (fdisk)
Expand the filesystem to the complete size of the partition (which was resized in step 3 above). This is setup as a shell script to run after reboot. (resize2fs)
Because there are minor differences in the size of SD cards, even different models from the same manufacturer, it would be extremely difficult to give a more specific set of commands.
#!/bin/sh
# Part of raspi-config http://github.com/asb/raspi-config
# ...
if ! [ -h /dev/root]; then
whiptail --msgbox '/dev/root does not exist or is not a symlink. Don't know how to expand" 20 60 2
return 0
fi
ROOT_PART=$(readlink /dev/root)
PART_NUM=${ROOT_PART#mmcblk0p}
if [ "$PART_NUM" = "$ROOT_PART" ]; then
whiptail --msgbox "/dev/root is not an SD card. Don't know how to expand" 20 60 2
return 0
fi
# NOTE: the NOOBS partition layout confuses parted. For now, let's only
# agree to work with a sufficiently simple partition layout
if [ "$PART_NUM" -ne 2 ]; then
whiptail msgbox "Your partition layout is not currently supported by this tool. You rae probably using NOOBS, in which case your root filesystem is already expanded anyway." 20 60 2
return 0
fi
LAST_PART_NUM=$(parted /dev/mmcblk0 -ms unit s p | tail -n 1 | cut -f 1 -d:)
if [ "$LAST_PART_NUM" != "$PART_NUM" ]; then
whiptail --msgbox "/dev/root is not the last partition. Don't know how to expand" 20 60 2
return 0
fi
# Get the starting offset of the root partition
PART_START=$(parted /dev/mmcblk0 -ms unit s p | grep "^${PART_NUM}" | cut -f 2 -d:)
[ "$PART_START" ] || return 1
# Return value will likely be error for fdisk as it fails to reload the
# partition table because the root fs is mounted
fdisk /dev/mmdblk0 <<EOF
p
d
$PART_NUM
n
p
$PART_NUM
$PART_START
p
w
EOF
ASK_TO_REBOOT=1
# now set up an init.d script
cat <<\EOF > /etc/init.d/resize2fs_once &&
#!/bin/sh
### BEGIN INIT INFO
# Provides: resize2fs_once
# Required-Start:
# Required-Stop:
# Default-Start: 2 3 4 5 S
# Default-Stop:
# Short-Description: Resize the root filesystem to fill partition
### END INIT INFO
. /lib/lsb/init-functions
case "$1" in
start)
log_daemon_msg "Starting resize2fs_once" &&
resize2fs /dev/root &&
rm /etc/init.d/resize2fs_once &&
update-rc.d resize2fs_once remove &&
log_end_msg $?
;;
*)
echo "Usage $0 start" >&2
exit 3
;;
esac
EOF
chmod +x /etc/init.d/resize2fs_once &&
update-rc.d resize2fs_once defaults &&
if [ '$INTERACTIVE" = True ]; then
whiptail --msgbox "Root partition has been resized.\nThe filesystem will be enlarged upon the next reboot" 20 60 2
fi
How can I, in a c program, perform a glob by using the function provided by the z shell?
I have created a README of my explorations so far. It is for use in an open source library.
https://bitbucket.org/sentimental/zsh_source_experimentation/src/master/README
I copy it here:
Start
Lets get the sources
apt-get source zsh
apt-get source zsh-dev
I've discovered by using ldd that zsh does not produce any library files::
#ldd /bin/zsh4
linux-gate.so.1 => (0xb7775000)
libcap.so.2 => /lib/i386-linux-gnu/libcap.so.2 (0xb7751000)
libdl.so.2 => /lib/i386-linux-gnu/libdl.so.2 (0xb774c000)
libtinfo.so.5 => /lib/i386-linux-gnu/libtinfo.so.5 (0xb772c000)
libm.so.6 => /lib/i386-linux-gnu/libm.so.6 (0xb7700000)
libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xb755b000)
I think I will have to use the source files directly.
Lets locate the files containing references to extended globbling
(I'm using zsh as my shell).::
grep -ir EXTENDEDGLOB . | egrep "\.(c|h):" | cut -d: -f1 | sort -u
./README
./zsh-4.3.17/Etc/ChangeLog-3.0
./zsh-4.3.17/Src/glob.c
./zsh-4.3.17/Src/Modules/zutil.c
./zsh-4.3.17/Src/options.c
./zsh-4.3.17/Src/pattern.c
./zsh-4.3.17/Src/utils.c
./zsh-4.3.17/Src/Zle/complist.c
./zsh-4.3.17/Src/Zle/zle_tricky.c
./zsh-4.3.17/Src/zsh.h
Lets consider a couple of those files
zsh.h
In here EXTENDEDGLOB is defined as part of an anonymous enum
There are publications
here
http://publications.gbdirect.co.uk/c_book/chapter6/enums.html
and here
http://bytes.com/topic/c/answers/63891-enum-within-function-standard
detailing the use of enum in c
An example of its use is probably the method arguments for the function
................
static int
bin_zregexparse(char *nam, char **args, Options ops, UNUSED(int func))
Found in the file
.................
./zsh-4.3.17/Src/Modules/zutil.c
Lets see what's calling that function. Hmm only one call. The only reference to that call is in that file.
grep -r bin_zregexparse . | egrep "\.(c|h):" | cut -d: -f1 | sort -u
./zsh-4.3.17/Src/Modules/zutil.c
Hmm.... How does it work if nothing calls this function?
Ok lets see if there is some conditional configuration that sets up or aliases this code somehow?
grep -i regex ./**/conf*
/zsh-4.3.17/config.h.in :/* Define to 1 if you have the `regexec' function. */
./zsh-4.3.17/config.h.in :#undef HAVE_REGEXEC
./zsh-4.3.17/config.h.in :/* Define to 1 if you have the `regexec' function. */
./zsh-4.3.17/config.h.in :#undef HAVE_REGEXEC
./zsh-4.3.17/configure : regcomp regexecc regerror regfree \
./zsh-4.3.17/configure : regcomp regexec regexecerror regfree \
./zsh-4.3.17/configure.ac : regcomp regexec regerrorror regfree \
Lets investigate these files.
config.h.in
Doesn't seem to exist, perhaps it is generated?
There seems to be a block in
configure
8148 for ac_func in strftime strptime mktime timelocal \
8149 difftime gettimeofday clock_gettime \
8150 select poll \
8151 readlink faccessx fchdir ftruncate \
etc etc etc ..
8178 htons ntohs \
8179 regcomp regexec regerror regfree \
8180 gdbm_open getxattr \
8181 realpath canonicalize_file_name \
8182 symlink getcwd
8183 do :
8184 as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
8185 ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
8186 if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
8187 cat >>confdefs.h <<_ACEOF
8188 #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
8189 _ACEOF
8190
8191 fi
8192 done
}}}
I've no idea what that is doing. TODO: Investigate!
In
./zsh-4.3.17/configure.ac
1167 dnl ---------------
1168 dnl CHECK FUNCTIONS
1169 dnl ---------------
1170 | rglobdata.gd_gf_noglobdot
1171 dnl need to integrate this function
1172 dnl AC_FUNC_STRFTIME
1173 | rglobdata.gd_gf_listtypes
1174 AC_CHECK_FUNCS(strftime strptime mktime timelocal \
1175 difftime gettimeofday clock_gettime \
1176 select poll \
etc etc etc
1205 regcomp regexec regerror regfree \
1206 gdbm_open getxattr \
1207 realpath canonicalize_file_name \
1208 symlink getcwd)
1209 AC_FUNC_STRCOLL
Not really sure at this stage how I can do this, consider that I perhaps want to unit-test that function, how might I do so?
The function bin_zregexparse is the implementation of the zregexparse builtin provided by the zsh/zutil module. It is used below its definition in zutil.c:
static struct builtin bintab[] = {
…
BUILTIN("zregexparse", 0, bin_zregexparse, 3, -1, 0, "c", NULL),
…
};
zregexparse is intended to be used in the implementation of _regex_arguments. This isn't the most promising entry point.
If you want to implement zsh's globbing features, you'll have to pull in almost all of the zsh code into your program, since glob patterns can contain arbitrary embedded code. You can exclude the line editor during build, but that's about it.
I would recommend using a separate zsh binary and feeding it requests through a pair of pipes.
setopt extended_glob null_glob
print -Nr -- **/*(.Om+my_predicate) ''