Script is running perfectly on co-workers devices but gives me 'Invalid cross-device link' - shell

My script is running perfectly on co-workers devices (MacOSX with Docker Desktop same as me), but gives me every time the same error and it does not move or only half, the libraries in the deps directory:
OSError: [Errno 18] Invalid cross-device link: '/tmp/pip-target-dzwe_2kc/lib/python/numpy' ->
'/foo/python/numpy'
My script :
#!/bin/bash
export PKG_DIR='python'
export SIDE_DEPS_DIR='deps'
rm -rf ${PKG_DIR} && mkdir -p ${PKG_DIR}
rm -rf ${SIDE_DEPS_DIR} && mkdir -p ${SIDE_DEPS_DIR}
docker run --rm -v $(pwd):/foo -w /foo lambci/lambda:build-python3.8 \
pip3 install -r requirements.txt -t ${PKG_DIR}
# move stuff to deps
find /${PKG_DIR} -maxdepth 1 -type d \
\( -name "pandas*" -o -name "numpy*" -o -name "numpy.libs*" -o -name "scipy*" -o -name "scipy.libs*" \) -exec mv '{}' ${SIDE_DEPS_DIR} \;
# zip side dependencies
zip -r ge_deps.zip deps
# zip layer
zip -r layers-python38-great-expectations.zip python
It's a script which uses a public lambda docker image to create a lambda layer (basically a zip that contains libraries) and which removes unwanted libraries to put them in another folder deps.
The above code will use the public Docker image lambci / lambda and will install in the empty python directory, libraries which come from a python package which is called 'great-expectations' and which helps to test pipelines of data (which is specified in requirements.txt and is great-expectations==0.12.7)
I have been stuck with this problem for a while and have not found a solution.

Had this exact problem just now.
/tmp and /foo are different devices - /tmp is within the docker OS and /foo is mapped to your local OS.
pip seems to be using shutil.rename() to move the built package from tmp to the final output location (/foo). This fails because they are different devices. Ideally pip would use shutil.move() instead, which will deal with a cross-device move.
As a workaround, you can change the temp folder used by PIP by setting TMPDIR before invoking the pip command. i.e. export TMPDIR=/foo/tmp before calling pip in the docker image. So, the whole command might be something like
docker run --rm -v $(pwd):/foo -w /foo lambci/lambda:build-python3.8 \
/bin/bash -c "export TMPDIR=/foo/tmp && pip3 install -r requirements.txt -t ${PKG_DIR}"
(multiple commands soln taken from https://www.edureka.co/community/10736/how-to-run-multiple-commands-in-docker-at-once - open to better suggestions!)
This will likely be slower because it's using the local OS for temp files, but it avoids the attempted 'rename' across devices from the temp folder to the final output folder.

Related

Uploading file to S3 Bucket from /tmp/

I automated my apache http logs to be stored in the tmp directory, which is running the script correctly until moving the file to the tmp directory. Now I have added few more lines of script to move those .tar files to the S3 bucket. When I perform this command manually they are getting moved to the s3 bucket but I do not want to do it everyday since its a daily job and I would want to automate them.
The .tar file is present in the /tmp/ directory when I manually go there and look but the awscl fails to locate to it.
The error I am getting is : the user provided path does not exist when I run the script.
the lines of code I added were these,
sudo apt update -y
sudo apt install apache2
sudo ufw allow 'Apache'
sudo systemctl start apache2
myname="abcd"
sudo tar -cvf $myname-httpd-logs-date +'%d%m%Y-%H%M%S'.tar /var/log/apache2/*.log
sudo mv *.tar /tmp/
sudo apt install awscli -y
s3_bucket="s3_test"
aws s3 \
cp /tmp/$myname-httpd-logs-$(date +'%d%m%Y-%H%M%S').tar \
s3://$s3_bucket/$myname-httpd-logs-date +'%d%m%Y-%H%M%S'.tar
Can anyone help me out in figuring out why this error has occurred and how to fix it.
Error
You appear to be calling datetime multiple times to construct different filenames. Rather than calling it multiple times, if you call it once, you will ensure that each time you refer to the tar filename, it uses the same name:
myname="abcd"
target_name=$myname-httpd-logs-`date +'%d%m%Y-%H%M%S'.tar`
sudo tar -cvf $target_name /var/log/apache2/*.log
sudo mv $target_name /tmp/
s3_bucket="s3_test"
aws s3 \
cp /tmp/$target_name \
s3://$s3_bucket/$target_name
There is not needed ' in your command in $(date +'%d%m%Y-%H%M%S). It should be:
aws s3 \
cp /tmp/$myname-httpd-logs-$(date +%d%m%Y-%H%M%S).tar \
s3://$s3_bucket/$myname-httpd-logs-${timestamp}.tar
And if you want the unneeded quote
aws s3 \
cp /tmp/$myname-httpd-logs-$(date +'%d%m%Y-%H%M%S').tar \
s3://$s3_bucket/$myname-httpd-logs-${timestamp}.tar
be sure to close it (the syntax color gives you a clue).

Dockerfile - ARG SHA and Curl

I am newbie to Docker. I can create a docker image for Java and Maven from https://github.com/carlossg/docker-maven/blob/master/jdk-13/Dockerfile . I can understand most of the commands there inside dockerfile, there are some that I could not find sufficient info on net. Can someone please help me ?
(1) What does below ARG SHA do. If I understand it right, SHA is immutable identifier that is associated with image, so I am downloading image with that identifier, I mean specific image with changes I want and stored with that SHA, is this right?
ARG SHA=c35a1803a6e70a126e80b2b3ae33eed961f83ed74d18fcd16909b2d44d7dada3203f1ffe726c17ef8dcca2dcaa9fca676987befeadc9b9f759967a8cb77181c0
(2) I know what RUN, echo does and how the variable works. But not sure what is happening below with curl command . No idea what below lines of code does for sure.
RUN mkdir -p /usr/share/maven /usr/share/maven/ref \
&& curl -fsSL -o /tmp/apache-maven.tar.gz ${BASE_URL}/apache-maven-${MAVEN_VERSION}-bin.tar.gz \
&& echo "${SHA} /tmp/apache-maven.tar.gz" | sha512sum -c - \
&& tar -xzf /tmp/apache-maven.tar.gz -C /usr/share/maven --strip-components=1 \
&& rm -f /tmp/apache-maven.tar.gz \
&& ln -s /usr/share/maven/bin/mvn /usr/bin/mvn```
You have to read it like a shell script.
1.
SHA is SHA512 hash
function used in line 10 to
check if downloaded /tmp/apache-maven.tar.gz is what we expect. It
has nothing to do with Docker image ID, if you mean that. You can
reproduce the check locally on your system:
$ SHA=c35a1803a6e70a126e80b2b3ae33eed961f83ed74d18fcd16909b2d44d7dada3203f1ffe726c17ef8dcca2dcaa9fca676987befeadc9b9f759967a8cb77181c0
$ BASE_URL=https://apache.osuosl.org/maven/maven-3/${MAVEN_VERSION}/binaries
$ curl -fsSL -o /tmp/apache-maven.tar.gz ${BASE_URL}/apache-maven-${MAVEN_VERSION}-bin.tar.gz
$ echo "${SHA} /tmp/apache-maven.tar.gz" | sha512sum -c -
/tmp/apache-maven.tar.gz: OK
(Notice that $ here is a command line
prompt
used to indicate start of a new line, not a part of the
command).
curl here downloads
https://apache.osuosl.org/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin.tar.gz
to /tmp/apache-maven.tar.gz.
2.
Again, read it like a shell script. && is used for chaining commands and \ is used to concatenate lines.
RUN mkdir -p /usr/share/maven /usr/share/maven/ref
Create /usr/share/maven and /usr/share/maven/ref directories.
curl -fsSL -o /tmp/apache-maven.tar.gz ${BASE_URL}/apache-maven-${MAVEN_VERSION}-bin.tar.gz
Download temporary apache-maven tarball to /tmp/apache-maven.tar.gz.
echo "${SHA} /tmp/apache-maven.tar.gz" | sha512sum -c -
Check if the downloaded tarball has the correct checksum.
tar -xzf /tmp/apache-maven.tar.gz -C /usr/share/maven --strip-components=1
Extract /tmp/apache-maven.tar.gz to /usr/share/maven.
rm -f /tmp/apache-maven.tar.gz
Remove temporary tarball after extracting it.
ln -s /usr/share/maven/bin/mvn /usr/bin/mvn
Create /usr/bin/mvn that points to /usr/share/maven/bin/mvn. This
is done because /usr/bin directory is typically in $PATH so that
mvn can be run without providing a full path to it.

How to install directory structure recursively in OpenEmbedded BitBake recipe?

I'd like to simplify a BitBake recipe that installs a large directory structure by using some sort of recursive install routine rather than calling install many times. The source directory layout is frequently changing during development, which is causing far more recipe revisions than I want to deal with.
As an example, how would the following do_install() be simplified from this:
do_install() {
install -d ${D}/foo
install -m 0644 ${S}/foo/*.* ${D}/foo
install -d ${D}/foo/a
install -m 0644 ${S}/foo/a/*.* ${D}/foo/a
install -d ${D}/foo/b
install -m 0644 ${S}/foo/b/*.* ${D}/foo/b
install -d ${D}/foo/c
install -m 0644 ${S}/foo/c/*.* ${D}/foo/c
install -d ${D}/bar
install -m 0644 ${S}/bar/*.* ${D}/bar
install -d ${D}/bar/a
install -m 0644 ${S}/bar/a/*.* ${D}/bar/a
install -d ${D}/bar/a/bananas
install -m 0644 ${S}/bar/a/bananas/*.* ${D}/bar/a/bananas
}
To something more like this pseudocode:
do_install() {
for each subdir in ${S}/foo/
install subdir recursively to ${D}/foo/subdir
end
for each subdir in ${S}/bar/
install subdir recursively to ${D}/bar/subdir
end
}
The top-level directories in our source files (foo & bar in the above example) rarely change, so calling them out in the recipe is fine. It's the lower level directories that are frequently changing.
It may be that cp -r ends up being the way to go, but I believe I've read that it's frowned upon in BitBake recipes, so I'm wondering if BitBake provides some alternate mechanism, or if there's
some other reasonably standardized way to do this.
We used to do it in that way:
do_install() {
find ${WORKDIR}/ -type f -exec 'install -m 0755 "{}" ${D}/var/www/' \;
}
The canonical form in OE is
cp -R --no-dereference --preserve=mode,links -v SOURCE DESTINATION
see the answer here (while they looks a bit different in code, the questions are semantically equivalent)

Downloading and automatically installing a tgz file

#!/bin/bash
mkdir /tmp
curl -O http://www.mucommander.com/download/nightly/mucommander-current.app.tar.gz /tmp/mucommander.tgz
tar -xvzf /tmp/mucommander.tgz */mucommander.app/*
cp -r /tmp/mucommander.app /Applications
rm -r /tmp
I'm trying to create a shell script to download and extract muCommander to my applications directory on a Mac.
I tried cd into the tmp dir, but then the script stops when I do that.
I can extract all using the -C argument, but the current tgz path is muCommander-0_9_0/mucommander.app, which could change on later builds, so I'm trying to keep it generic.
Can anyone give me pointers where I'm going wrong?
Thanks in advance.
Strip the first path component when you untar the archive, from tar(1):
--strip-components count
(x mode only) Remove the specified number of leading path ele-
ments. Pathnames with fewer elements will be silently skipped.
Note that the pathname is edited after checking inclusion/exclu-
sion patterns but before security checks.
Update
Here is a working bash example of how to, fairly generically, copy the contents of the tgz file to /Applications.
shopt -s nocaseglob
TMPDIR=/tmp
APP=mucommander
TMPAPPDIR=$TMPDIR/$APP
mkdir -p $TMPAPPDIR
curl -o $TMPDIR/$APP.tgz http://www.mucommander.com/download/nightly/mucommander-current.app.tar.gz
tar --strip-components=1 -xvzf $APP.tgz -C $TMPAPPDIR
mv $TMPAPPDIR/${APP}* /Applications
# rm -rf $TMPAPPDIR $TMPDIR/$APP
The rm command is commented out for now, verify that it does no harm before you use it.
The following will update your muCommander.
#for the safety, remove old temporary extraction from the /tmp
rm -rf /tmp/muCommander.app
#kill the running mucommander - you dont want replace the runnung app
ps -ef | grep ' /Applications/muCommander.app/' | grep -v grep | awk '{print $2}' | xargs kill
#download, extract, remove old, move new, open
#each command run only when the previous ended with success
curl http://www.mucommander.com/download/nightly/mucommander-current.app.tar.gz |\
tar -xzf - -C /tmp --strip-components=1 '*/muCommander.app' && \
rm -rf /Applications/muCommander.app && \
mv /tmp/muCommander.app /Applications && \
open /Applications/muCommander.app
Beware, after the '\' must following new line, and not any spaces...

How to unpack and pack pkg file?

I have a pkg file created by Install Maker for Mac.
I want to replace one file in pkg. But I must do this under Linux system, because this is a part of download process. When user starts to download file server must replace one file in pkg.
I have a solution how unpack pkg and replace a file but I dont know how pack again to pkg.
http://emresaglam.com/blog/1035
http://ilostmynotes.blogspot.com/2012/06/mac-os-x-pkg-bom-files-package.html
Packages are just .xar archives with a different extension and a specified file hierarchy. Unfortunately, part of that file hierarchy is a cpio.gz archive of the actual installables, and usually that's what you want to edit. And there's also a Bom file that includes information on the files inside that cpio archive, and a PackageInfo file that includes summary information.
If you really do just need to edit one of the info files, that's simple:
mkdir Foo
cd Foo
xar -xf ../Foo.pkg
# edit stuff
xar -cf ../Foo-new.pkg *
But if you need to edit the installable files:
mkdir Foo
cd Foo
xar -xf ../Foo.pkg
cd foo.pkg
cat Payload | gunzip -dc |cpio -i
# edit Foo.app/*
rm Payload
find ./Foo.app | cpio -o | gzip -c > Payload
mkbom Foo.app Bom # or edit Bom
# edit PackageInfo
rm -rf Foo.app
cd ..
xar -cf ../Foo-new.pkg
I believe you can get mkbom (and lsbom) for most linux distros. (If you can get ditto, that makes things even easier, but I'm not sure if that's nearly as ubiquitously available.)
Here is a bash script inspired by abarnert's answer which will unpack a package named MyPackage.pkg into a subfolder named MyPackage_pkg and then open the folder in Finder.
#!/usr/bin/env bash
filename="$*"
dirname="${filename/\./_}"
pkgutil --expand "$filename" "$dirname"
cd "$dirname"
tar xvf Payload
open .
Usage:
pkg-upack.sh MyPackage.pkg
Warning: This will not work in all cases, and will fail with certain files, e.g. the PKGs inside the OSX system installer. If you want to peek inside the pkg file and see what's inside, you can try SuspiciousPackage (free app), and if you need more options such as selectively unpacking specific files, then have a look at Pacifist (nagware).
You might want to look into my fork of pbzx here: https://github.com/NiklasRosenstein/pbzx
It allows you to stream pbzx files that are not wrapped in a XAR archive. I've experienced this with recent XCode Command-Line Tools Disk Images (eg. 10.12 XCode 8).
pbzx -n Payload | cpio -i
In addition to what #abarnert said, I today had to find out that the default cpio utility on Mountain Lion uses a different archive format per default (not sure which), even with the man page stating it would use the old cpio/odc format. So, if anyone stumbles upon the cpio read error: bad file format message while trying to install his/her manipulated packages, be sure to include the format in the re-pack step:
find ./Foo.app | cpio -o --format odc | gzip -c > Payload
#shrx I've succeeded to unpack the BSD.pkg (part of the Yosemite installer) by using "pbzx" command.
pbzx <pkg> | cpio -idmu
The "pbzx" command can be downloaded from the following link:
pbzx Stream Parser
If you are experiencing errors during PKG installation following the accepted answer, I will give you another procedure that worked for me (please note the little changes to xar, cpio and mkbom commands):
mkdir Foo
cd Foo
xar -xf ../Foo.pkg
cd foo.pkg
cat Payload | gunzip -dc | cpio -i
# edit Foo.app/*
rm Payload
find ./Foo.app | cpio -o --format odc --owner 0:80 | gzip -c > Payload
mkbom -u 0 -g 80 Foo.app Bom # or edit Bom
# edit PackageInfo
rm -rf Foo.app
cd ..
xar --compression none -cf ../Foo-new.pkg
The resulted PKG will have no compression, cpio now uses odc format and specify the owner of the file as well as mkbom.
Bash script to extract pkg: (Inspired by this answer:https://stackoverflow.com/a/23950738/16923394)
Save the following code to a file named pkg-upack.sh on the $HOME/Downloads folder
#!/usr/bin/env bash
filename="$*"
dirname="${filename/\./_}"
mkdir "$dirname"
# pkgutil --expand "$filename" "$dirname"
xar -xf "$filename" -C "$dirname"
cd "$dirname"/*.pkg
pwd
# tar xvf Payload
cat Payload | gunzip -dc |cpio -i
# cd usr/local/bin
# pwd
# ls -lt
# cp -i * $HOME/Downloads/
Uncomment the last four lines, if you are using a rudix package.
Usage:
cd $HOME/Downloads
chmod +x ./pkg-upack.sh
./pkg-upack.sh MyPackage.pkg
This was tested with the ffmpeg and mawk package from rudix.org (https://rudix.org) search for ffmpeg and mawk packages on this site.
Source : My open source projects : https://sourceforge.net/u/nathan-sr/profile/

Resources