Startup script doesn't seem to work - google-compute-engine

I've recently started using Google's Compute engine for some of my projects the problem is my startup script doesn't seem to work, For some reason my script just doesn't work, the VM has the startup-script metadata and it works fine when I run it manually with:
sudo google_metadata_script_runner --script-type startup
Here is what I am trying to run on startup:
#!/bin/bash
sudo apt-get update
sudo rm -f Eve.jar
sudo rm -f GameServerStatus.jar
wget <URL>/Eve.jar
wget <URL>/GameServerStatus.jar
sudo chmod 7777 Eve.jar
sudo chmod 7777 GameServerStatus.jar
screen -dmS Eve sh Eve.sh
screen -dmS PWISS sh GameServerStatus.sh
There are no errors in the log either, it just seems to stop at the chmod or screen commands, Any ideas?
Thanks!

To add to kangbu's answer:
Checking the logs in container-optimized OS by
sudo journalctl -u google-startup-scripts.service
showed that the script could not find the user. After a long time of debugging I finally added a delay before the sudo and now it works. Seems the user is not registered when the script runs.
#! /bin/bash
sleep 10 # wait...
cut -d: -f1 /etc/passwd > /home/user/users.txt # make sure the user exists
cd /home/user/project # cd does not work after sudo, do it before
sudo -u user bash -c '\
source /home/user/.bashrc && \
<your-task> && \
date > /home/user/startup.log'

I have the same problem #Brina mentioned. I set up metadata key startup-script and value like:
touch a
ls -al > test.txt
When I ran the script above sudo google_metadata_script_runner --script-type startup, it worked perfectly, However if I reset my VM instance the startup script didn't work. So, I checked startup script logs
...
Jul 3 04:30:37 kbot-6 ntpd[1514]: Listen normally on 5 eth0 fe80::4001:aff:fe8c:7 UDP 123
Jul 3 04:30:37 kbot-6 ntpd[1514]: peers refreshed
Jul 3 04:30:37 kbot-6 ntpd[1514]: Listening on routing socket on fd #22 for interface updates
Jul 3 04:30:38 kbot-6 startup-script: INFO Starting startup scripts.
Jul 3 04:30:38 kbot-6 startup-script: INFO Found startup-script in metadata.
Jul 3 04:30:38 kbot-6 startup-script: INFO startup-script: Return code 0.
Jul 3 04:30:38 kbot-6 startup-script: INFO Finished running startup scripts.
Yes. they found startup-script and ran it. I guessed it had executed as an another user. I changed my script like this:
pwd > /tmp/pwd.txt
whoami > /tmp/whoami.txt
The result is:
myuserid#kbot-6:/tmp$ cat pwd.txt whoami.txt
/
root
Yes. It was executed at the / diectory as root user. Finally, I changed my script to sudo -u myuserid bash -c ... which run it by specified userid.

Go to the VM instances page.
Click on the instance for which you want to add a startup script.
Click the Edit button at the top of the page.
Under Custom metadata, click Add item.
Add your startup script using one of the following keys:
startup-script: Supply the startup script contents directly with this key.
startup-script-URL: Supply a Google Cloud Storage URL to the start script file with this key.
It is working. The documentation for the new instance and existing instance as shown in GCE Start Up Script
Startup script output is written to the following log files:
CentOS and RHEL: /var/log/messages
Debian: /var/log/daemon.log
Ubuntu 14.04, 16.04, and 16.10: /var/log/syslog
On Ubuntu 12.04, SLES 11 and 12, and all images older than v20160606:
sudo /usr/share/google/run-startup-scripts

think that you do not need sudo, as well as the chmod 7777 should be 777
also a cd (or at least a pwd) at the beginning might be useful.
... log to text file, in order to know where the script may fail.

Related

Error in running the shutdown-script for instance of google compute engine: gsutil failed to copy file to google cloud storage

I use a shutdown-script to backup the files on an instance before it is shutdown.
In this shutdown-script, the gsutil tool is used to send files to a bucket at google cloud storage.
/snap/bin/gsutil -m rsync -d -r /home/ganjin/notebook gs://ganjin-computing/XXXXXXXXXXX/TEST-202104/notebook
It worked well for long days. But recently, there occurs some error as below.
If I run the code manually, it works well. It seems that there is something wrong with jobs management of systemd.
Could anyone give me some hint?
INFO shutdown-script: /snap/bin/gsutil -m rsync -d -r /home/ganjin/notebook gs://ganjin-computing/XXXXXXXXXXX/TEST-202104/notebook
Apr 25 03:00:41 instance-XXXXXXXXXXX systemd[1]: Requested transaction contradicts existing jobs: Transaction for snap.google-cloud-sdk.gsutil.d027e14e-3905-4c96-9e42-c1f5ee9c6b1d.scope/start is destructive (poweroff.target has 'start' job queued, but 'stop' is included in transaction).
Apr 25 03:00:41 instance-XXXXXXXXXXX shutdown-script: INFO shutdown-script: internal error, please report: running "google-cloud-sdk.gsutil" failed: cannot create transient scope: DBus error "org.freedesktop.systemd1.TransactionIsDestructive": [Transaction for snap.google-cloud-sdk.gsutil.d027e14e-3905-4c96-9e42-c1f5ee9c6b1d.scope/start is destructive (poweroff.target has 'start' job queued, but 'stop' is included in transaction).]
Update gsutil with -f option.
update gsutil -f
If the above command doesn’t work then try the command below:
sudo apt-get update && sudo apt-get --only-upgrade install google-cloud-sdk
Update guest environment and try to shutdown the instance. Use the link below as a reference to update the guest environment.
https://cloud.google.com/compute/docs/images/install-guest-environment#update-guest
If still facing issues do forceful shutdown:
sudo poweroff -f

MySQL Docker file : sed: couldn't open temporary file

I am trying to create new MySQL image and deploying in Kubernetes.
FROM oraclelinux:7-slim
USER root
ARG MYSQL_SERVER_PACKAGE=mysql-community-server-minimal-8.0.19
ARG MYSQL_SHELL_PACKAGE=mysql-shell-8.0.19
# Install server
RUN yum install -y https://repo.mysql.com/mysql-community-minimal-release-el7.rpm \
https://repo.mysql.com/mysql-community-release-el7.rpm \
&& yum-config-manager --enable mysql80-server-minimal \
&& yum install -y \
$MYSQL_SERVER_PACKAGE \
$MYSQL_SHELL_PACKAGE \
libpwquality \
&& yum clean all \
&& mkdir /docker-entrypoint-initdb.d
VOLUME /var/lib/mysql
COPY docker-entrypoint.sh /entrypoint.sh
COPY healthcheck.sh /healthcheck.sh
ENTRYPOINT ["/entrypoint.sh"]
HEALTHCHECK CMD /healthcheck.sh
EXPOSE 3306 33060
RUN chmod +rwx /entrypoint.sh
RUN chmod +rwx /healthcheck.sh
RUN groupadd -r mysql && useradd -r -g mysql mysql
EXPOSE 3306
CMD ["mysqld"]
It's working fine in the container. But throwing error when I deployed in Kubernetes like below:
How can I understand this issue?
ADDED
docker-entrypoint.sh:
if [ -n "$MYSQL_LOG_CONSOLE" ] || [ -n "console" ]; then
# Don't touch bind-mounted config files
if ! cat /proc/1/mounts | grep "/etc/my.cnf"; then
sed -i 's/^log-error=/#&/' /etc/my.cnf
fi
fi
P.S : I have added content of the file.
The problem is related with sed's in-place editing implementation. When you edit a file using the -i or --in-place option, the edition doesn't actually happen in-place. sed saves the changes into a temporary file and then uses it to replace the original one.
It happens that you don't have write permission to /etc directory, where sed is trying to create its temporary file.
As suggested in comments most probably the command is run by user mysql. For sure it is not run as root as it has enough privileges to be able to write to /etc:
bash-4.2# ls -ld /etc
drwxr-xr-x 1 root root 4096 Mar 27 15:04 /etc
As you can see others don't have write permission. Changing permissions or owner of /etc directory itself is a really bad idea and I won't advise you to run this command as root user either.
The simplest solution is to give up on using --in-place option, save the result in a directory such as /tmp, to which everyone has access:
bash-4.2# ls -ld /tmp
drwxrwxrwt 1 root root 4096 Mar 27 16:39 /tmp
and after that replace the content of the original file with the content of the temporary one.
Your command may look like this:
sed 's/^log-error=/#&/' /etc/my.cnf > /tmp/my.cnf && cat /tmp/my.cnf > /etc/my.cnf
One important caveat:
You need to make sure you have write permission on /etc/my.cnf file. As you can see below, by default you don't have such permission either, so the error will occur later, when the command will try to write to the original config file.
bash-4.2# ls -l /etc/my.cnf
-rw-r--r-- 1 root root 1239 Mar 27 15:04 /etc/my.cnf
You need to modify it in your Dockerfile either by making it availeble for edit by everyone:
RUN chmod 666 /etc/my.cnf
or better option:
RUN chown mysql /etc/my.cnf
to change its owner to mysql, if this is the user that executes the entrypoint.sh script.
Please let me know if it helps.

How do I run mysqld as root in the official MySql docker image?

First off, I know not to run as root normally. I have an abnormal situation: I need to use mysqldump with the --tab argument, which requires permission to write to disk, and I want to use those files outside the Docker container. I could explain why running mysqld as root makes this easier, but isn't this question long enough? Running as root is safe in this case because the container will be used only for running tests and for updating DB backup scripts based on SQL migration scripts, and it will be started to do 1 job and then taken back down again.
When I google for how to run mysqld as root, I find the answer indirectly given in instructions on how to NOT run as root. Among other things in order to run mysqld as user_name:
Start the server as user user_name. Another alternative is to start mysqld as the Unix root user and use the --user=user_name option.
To start the server as the given user automatically at system startup time, specify the user name by adding a user option to the [mysqld] group of the /etc/my.cnf option file or the my.cnf option file in the server's data directory.
Do we do one of those? Both of those? I'll assume both just in case. But do they really mean /etc/my.cnf, or does that depend on the installation (e.g. what Linux distribution)? E.g. Docker image mysql:5.6 has /etc/mysql/my.cnf. The directions for the MySql Docker image advise mounting a volume at /etc/mysql/conf.d which is referenced in the aforementioned my.cnf. (Doing so overwrites 2 configuration files that are there by default, so I used a COPY command in my Dockerfile instead to merely add a config file.) The file does make it into the container:
root#4f612d10a690:/etc/mysql/conf.d# cat my.cnf
[mysqld]
user=root
One further requirement from the MySql manual is to add the --user=root argument to mysqld. The official MySql image calls mysqld via its CMD, so I override that in my Dockerfile. My CMD command does indeed run (it is run in 2 places in official MySql image's entrypoint script):
# ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
mysql 1 0.1 2.8 1452788 472756 ? Ssl 14:24 0:01 mysqld --user=root
Note that mysqld has the --user=root command I provided, but is running as the mysql user, not as root.
Here's my full Dockerfile:
FROM mysql:5.6
VOLUME ["/var/lib/mysql-files"]
COPY ["my.cnf", "/etc/mysql/conf.d"]
CMD ["mysqld", "--user=root"]
My only guess as to why it's not running as root is that they mysql image's entrypoint script changes to the mysql user before running:
# allow the container to be started with `--user`
if [ ...blah... -a "$(id -u)" = '0' ]; then
...blah...
exec gosu mysql "$BASH_SOURCE" "$#"
fi
The above snippet basically says, if the user is root, then run the supplied arguments (the CMD + args in this case) as the mysql user.
Is running mysqld as root simply not supported by the official MySql Docker image?
Note: this is how to run mysqld process as SO's root user, and not how to get the root MySQL user.
I don't know whether exists a better approach but this works.
Viewing the official entrypoint.sh, it seems that it has no support of chaging the default mysql user
I realized how to run mysql as root but you need to have already initialized the data directory.
Step 1) Start a normal mysql in order to initialize a volume (the mysql entrypoint.sh will do that job):
docker run \
--rm \
-v $(pwd)/mysql/:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD="abc" \
mysql:5.6
Step 2) Stop and remove that container:
docker stop <container-id>
Step 3) Start again a new mysql process based on the data dir that has been created, but this time avoid to run the official mysql entrypoint:
docker run \
-v $(pwd)/mysql/:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD="abc" \
--entrypoint mysqld \
mysql:5.6 \
--user root
Step 4) Check it:
▶ docker exec -it 4add4d065c3e bash
root#4add4d065c3e:/# ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 2.8 23.0 1314864 471104 ? Ssl 15:12 0:00 mysqld --user root
root 28 3.0 0.1 20248 3040 ? Ss 15:12 0:00 bash
root 34 0.0 0.1 17500 2068 ? R+ 15:12 0:00 ps aux

Permission denied errors when creating app with custom OpenShift cartridge

I'm using OpenShift Origin and developing a cartridge for the first time. When my bin/install and bin/control scripts are running I've noticed "Permission denied" errors when they try to access anything in the cartridge usr dir. In the node platform.log I see the offending command that OpenShift runs looks like this (where my bin/control start tries to run a script in usr):
/sbin/runuser -s /bin/sh 5351e627ee5a934f290001d2 -c "exec /usr/bin/runcon 'unconfined_u:system_r:openshift_t:s0:c0,c1004' /bin/sh -c \"set -e; /var/lib/openshift/5351e627ee5a934f290001d2/mycart/bin/control start \""
Since the usr dir is a symlink I originally thought it was related to that, but now I think it's related to selinux (which I don't know much about). If I do a "ls -Z" on my app's cartridge dir the files are "system_u:object_r:openshift_var_lib_t:s0:c0,c1004" but the contents of the usr dir are "unconfined_u:object_r:default_t:s0", so it doesn't match what's in the above command.
I used the oo-admin-cartridge command to install the cartridge to my Origin VM.
Any ideas on how to fix this?
What I ended up doing was running "chcon -R -u system_u -t bin_t usr/" before installing the cartridge with oo-admin-cartridge. Built-in cartridges are not affected by this problem (checked nodejs), so I feel like it might be a oo-admin-cartridge bug. I would expect it to massage the selinux permissions instead of using whatever I provide.

"tcpdump -w 1.pcap" works, but "tcpdump -C 100 -w 1.pcap" - permission denied

I need to limit file size when I run "tcpdump -w 1.pcap". I try to do this with the key "-C", but when I add it I get error "permission denied". So:
> sudo tcpdump -w 1.pcap
tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
^C821 packets captured
847 packets received by filter
24 packets dropped by kernel
But:
> sudo tcpdump -C 100 -w 1.pcap
tcpdump: 1.pcap: Permission denied
I run the command from my home directory and I tried to remove and create the file before running the command with different permissions, finally I have:
-rwxrwxrwx 1 root root 0 Aug 5 10:30 1.pcap
or
-rwxrwxrwx 1 fd8 users 0 Aug 5 10:30 1.pcap
Could you suggest why in the second case I can't write to the file?
You need to do -Z root. Read the man page:
-Z Drops privileges (if root) and changes user ID to user and the group ID to the primary group of user.
This behavior is enabled by default (-Z tcpdump), and can be disabled by -Z root.
I experienced similar issues on Ubuntu 12.04 LTS and my case was fixed as below procedures.
sudo apt-get install apparmor-utils
The aa-complain command which referred by user2704275 is included in this package.
If your environment is RedHat/CentOS distro, you can same command by yum.
sudo aa-complain /usr/sbin/tcpdump
This will change AppArmor mode of tcpdump from "enforce" to "complain".
You can check AppArmor status in /sys/kernel/security/apparmor/profiles.
Then I can success to get tcpdump with sudo.
After getting tcpdump, for security reason, you might revert apparmor status to previous mode as below command.
sudo aa-enforce /usr/sbin/tcpdump
Regards.
I experienced similar problems when I tried to read from file, like
tcpdump -r example.cap 'icmp[icmptype] = icmp-echo'
For me AppArmor caused the problem I had to switch from 'enforcement' mode to 'complain' mode on 'tcpdump'. Run the following command as root:
aa-complain /usr/sbin/tcpdump