1

This morning I upgraded my PHP version to 7.1 and am seeing an issue when cron tries to run php /var/www/html/artisan schedule:run (a simple PHP command) I see the output:

3/3/2017 10:39:00 AMcrond: can't set groups: Operation not permitted
3/3/2017 10:39:00 AMcrond: USER www-data pid 1562 cmd php /var/www/html/artisan schedule:run
3/3/2017 10:40:00 AMcrond: can't set groups: Operation not permitted
3/3/2017 10:40:00 AMcrond: USER www-data pid 1563 cmd php /var/www/html/artisan schedule:run
3/3/2017 10:41:00 AMcrond: can't set groups: Operation not permitted
3/3/2017 10:41:00 AMcrond: USER www-data pid 1564 cmd php /var/www/html/artisan schedule:run
3/3/2017 10:42:00 AMcrond: can't set groups: Operation not permitted
3/3/2017 10:42:00 AMcrond: USER www-data pid 1565 cmd php /var/www/html/artisan schedule:run
3/3/2017 10:43:00 AMcrond: can't set groups: Operation not permitted
3/3/2017 10:43:00 AMcrond: USER www-data pid 1566 cmd php /var/www/html/artisan schedule:run

The command being run is a Laravel artisan command. It's run every minute allowing other scheduled work to be completed within the application itself. There's nothing in this command that writes to any files or anything like that. The scheduled work talks to a database and sends some email. Application logs are sent to stdout since it's a Docker container.

cron is run in a container with the command crond -f -d 8. Here's the Dockerfile:

# This container should be used for any/all CLI processes
# including cron, queues, etc.
FROM php:7.1-alpine

# Copy the application files to the container
ADD . /var/www/html

WORKDIR /var/www/html

# fix permissions in CI
RUN sed -ri 's/^www-data:x:82:82:/www-data:x:1000:1000:/' /etc/passwd \
    && sed -ri 's/^www-data:x:82:/www-data:x:1000:/' /etc/group

# Install Composer dependencies
RUN apk add --update --no-cache git zip unzip \

        # needed for spatie/laravel-backup
        mysql-client \

        # needed for gd
        libpng-dev libjpeg-turbo-dev \

    && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*

RUN docker-php-ext-install pdo_mysql gd \

        # needed for forking processes in laravel queues as of Laravel 5.3
        pcntl

# Ownership of the app dir for www-data
RUN chown -R www-data:www-data /var/www/html /home/www-data/

# Put php artisan schedule:run in a crontab
RUN echo "*       *       *       *       *       php /var/www/html/artisan schedule:run" > /etc/crontabs/www-data

# Make sure when users get into the container they aren't root
USER www-data

I've ruled out that php artisan schedule:run is the cause since I can run it manually and everything's fine. This means it's something within cron.

What is cron doing under the covers that could cause this error?

0
2
+50

Its because of one of these two conditions according to man 2 setgroups

   EPERM  The calling process has insufficient privilege (the caller
          does not have the CAP_SETGID capability in the user namespace
          in which it resides).

   EPERM (since Linux 3.19)
          The use of setgroups() is denied in this user namespace.  See
          the description of /proc/[pid]/setgroups in
          user_namespaces(7).

I imagine you are not using user namespaces, in which case the capability CAP_SETGID isn't permitted in the docker container. You'll need to alter the containers capability sets to fix it.

2
  • Ah, I would've never known to run man 2 setgroups, thank you!
    – Webnet
    Mar 8 '17 at 18:28
  • This answer was pivotal in my ability to debug the issue, but the specific solution in my case was that I wasn't running cron as root. This meant that the www-data user was trying to set the group of a process, which it did not have permission to do.
    – Webnet
    Mar 9 '17 at 2:18
0

You are running cron, just to have this command run in the background:

RUN echo "*       *       *       *       *       php /var/www/html/artisan schedule:run" > /etc/crontabs/www-data

Replace cron with sh should let you /not/ resort to increasing container caps:

  artisan_schedule_run:
    image: your-app-image
    command: /dumb-init /bin/sh -c "while true; do su www-data -c \"php /var/www/html/artisan schedule:run\" & sleep 60; done"

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.